java线程中断机制

利用标志变量

通过检查volatile类型的标志变量控制线程中断,不使用volatile类型的标志变量会导致jvm对内存的优化引起死循环

public class StopThread {
    private static volatile boolean stopRequested;

    public static void main(String[] args) throws InterruptedException {
        Thread backgroundThread = new Thread(new Runnable() {
            public void run() {
                int i = 0;
                while (!stopRequested) {
                    i++;
                }
            }
        });

        backgroundThread.start();

        TimeUnit.SECONDS.sleep(1);
        stopRequested = true;
    }
}

interrupt中断

如果不通过像上述这样的标志变量中断线程,也可以利用Thread类的相关方法进行中断

header 1header 2
public static boolean interrupted测试当前线程是否已经中断。线程的中断状态 由该方法清除。换句话说,如果连续两次调用该方法,则第二次调用将返回 false(在第一次调用已清除了其中断状态之后,且第二次调用检验完中断状态前,当前线程再次中断的情况除外)。
public boolean isInterrupted()测试线程是否已经中断。线程的中断状态不受该方法的影响。
public void interrupt()中断线程。

Thread.interrupt方法可以中断线程正在执行的会抛出InterruptedException的方法时,执行interrupt方法的时候该线程会抛出异常,以异常的方式中断线程,比如下面这个例子

例一

public static void main(String[] args) throws InterruptedException {
        Thread thread=new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    TimeUnit.SECONDS.sleep(60);
                } catch (InterruptedException e) {
                    //执行后续清理
                    System.err.println("this thread has been notified...");
                }

            }
        });
        thread.start();
        //等待让thread线程开始运行
        TimeUnit.SECONDS.sleep(1);
        thread.interrupt();
        System.out.println("finish");
    }

sleep方法会抛出InterruptedException,sleep方法是一个可中断的方法,上面这个例子thread线程处于sleep状态时,mian线程调用interrupt方法中断了正在睡眠的线程.在catch中务必进行资源的清理工作,thread.interrupt()方法不能中断正在等待锁或者正在等待I/O的线程.如果想要关闭I/O等待的资源可以直接关闭底层资源来终止线程,而对于锁等待的线程终止在下面会有案例.在这个例子中尤其要注意一点,InterruptedException异常被捕获之后,中断状态会被重设为false

例二

Java中断机制是一种协作机制,也就是说通过中断并不能直接终止另一个线程,而需要被中断的线程自己处理中断。在下面这个例子中,我们检查Thread类的标志变量的方法来中断线程

class Compute implements Runnable {

    @Override
    public void run() {
        double d = 1.0;

        while (!Thread.interrupted()) {

            d = d + (Math.PI + Math.E) / d;

        }
    }
}

public class NonInterrupTest {
    public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread(new Compute());
        thread.start();
        TimeUnit.SECONDS.sleep(2);
        thread.interrupt();
        System.out.println("interrupt...");
    }
}

再强调下上文提到的一点Thread.interrupted()方法在调用之后Thread的标志变量会被复位

ReentrantLock

上文提到对于正在进行锁等待的线程,我们无法通过Thread.interrupt方法立即中断线程,那么有没有一种锁可以在被interrupt时中断锁等待呢?实际上我们可以通过lockInterruptibly方法实现


class BlockMutex {
    private Lock lock = new ReentrantLock();

    public BlockMutex() {
        lock.lock();
    }

    public void f() {
        try {
            lock.lockInterruptibly();
            System.out.println("lock acquire in f() ");
        } catch (InterruptedException e) {
            //资源清理
            e.printStackTrace();
        }
    }

}

class MyBlockThread implements Runnable {

    private BlockMutex blockMutex;

    public MyBlockThread(BlockMutex blockMutex) {
        this.blockMutex = blockMutex;
    }

    @Override
    public void run() {
        System.out.println("waiting lock in f()");
        blockMutex.f();
        System.out.println("broken out of blocked call");
    }
}

public class MyLockInterruptTest {
    public static void main(String[] args) throws InterruptedException {
        //线程创建BlockThread同时就持有了blockMutex锁
        BlockMutex blockMutex = new BlockMutex();
        Thread thread = new Thread(new MyBlockThread(blockMutex));
        thread.start();
        TimeUnit.SECONDS.sleep(1);
        //中断锁等待
        thread.interrupt();
    }
}

主线程在创建BlockMutex时就持有对象锁,另一线程在等待获取BlockMutex对象锁时是就中断该线程

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值