正确使用interupt中断线程

不安全的中断方式:循环中设置标志位flag
public static class FalgCancelDemo implements Runnable{
        private volatile boolean flag=true;
        @Override
        public void run() {
            while(flag){
                //domywork (自己的业务逻辑)
                Thread.sleep(10000); 
            }
        }
        //中断方法
        public void cancel(){
            flag=false;
        }
    }

中断线程的时候如果我的业务逻辑是个阻塞的逻辑,那么设置flag是不能立马中断线程的,线程仍然会等sleep结束或者自己的业务逻辑执行结束才能中断,这就造成用户要求中断,但中断之后仍然没有中断的尴尬局面。

解决方法:循环中设置标志位flag,同时加入interupted判断
public static class InteruputCancelDemo implements Runnable{
        private volatile boolean flag=true;
        @Override
        public void run() {
            while (flag && !Thread.currentThread().isInterrupted()){
                try {
                    Thread.sleep(100);//这种阻塞方法会一直检查当前线程的标志位
                } catch (InterruptedException e) {
                    Thread.currentThread().interrupt();
                    e.printStackTrace();
                }
            }
        }
        //中断方法
        public void cancel(Thread toInteruptThread){
            flag=false;
            toInteruptThread.interrupt();//设置要中断线程标志位为false
        }
    }
注意点:程序捕获异常之后会隐含调用Thread.interrputed()方法,将中断标志位会改成false

聪明的你可能看到在捕获异常的时候加了一句Thread.currentThread().interrupt();这里也是大有学问。当然在这段代码中是并没有实质性的效果的。下面再看一段代码

public static class InteruptDemo implements Runnable{
        private Object lock=new Object();
        private int i;
        @Override
        public void run() {
            while(!Thread.currentThread().isInterrupted()){
                try{
                    synchronized (lock){
                        lock.wait();
                        System.out.println(i++);
                    }
                }catch (InterruptedException e){
                    System.out.println("当前线程的标志位:"+Thread.currentThread().isInterrupted());
                    Thread.currentThread().interrupt();
                    System.out.println("当前线程的标志位:"+Thread.currentThread().isInterrupted());
                }

            }
        }
        public void cancle(Thread thread){
            thread.interrupt();
        }

下面是main方法:

public static void main(String[] args) throws InterruptedException {
        InteruptDemo interuptDemo=new InteruptDemo();
        Thread test=new Thread(interuptDemo);
        test.start();
        Thread.sleep(10);
        interuptDemo.cancle(test);
    }

程序输出:

当前线程的标志位:false
当前线程的标志位:true

诸如wait(),sleep()等会抛出中断异常的方法,在程序执行的过程中都会去检查当前线程的中断标志位,如果标志位为true就会抛出中断异常,但是在抛出异常后,中断标志位会改成自动复位为false,可以理解为这些方法会隐含调用Thread.interrputed()方法。所以说如果我们在捕获异常之后不加Thread.currentThread().interrupt();就会导致程序仍然不能正常结束。

你可能感兴趣的:(正确使用interupt中断线程)