美文网首页
线程中断

线程中断

作者: 四喜汤圆 | 来源:发表于2020-06-08 13:03 被阅读0次

    摘抄朴实的聊聊很多人会误解/不懂的Java并发中断机制

    一、作用

    1. 什么是中断

    原来对中断的理解可能是:

    你:在打游戏
    女朋友:别打游戏了,赶快过来吃饭
    你:听到女朋友招呼之后立马中断手中的游戏乖乖过去吃饭

    其实是:

    在多线程中,『中断是一种协同机制』。就是女朋友叫你吃饭,你收到了中断游戏通知,但是否马上放下手中的游戏去吃饭看你心情

    2. 为什么有中断

    二、概念

    每个线程对象都有一个boolean类型的标志,代表是否有中断请求,该标志通过底层 native 实现。

    几个相关方法

    1. Thread 的实例方法interrupt()

    唯一一个可以将中断标志设为true的方法

    线程被中断的反应是不一样的,脾气不好的直接抛出InterruptedException

    这些可能阻塞的方法如果声明有throws InterruptedExcetion,也就是暗示我们它们是可中断的。

    2. Thread 的实例方法isInterrupted()

    返回当前中断标志

    • true
      线程被中断

    • false
      线程没被中断或被清空了中断标志

    3. Thread 的静态方法interrupted()

    返回当前中断标志,并清空中断标志

    三、使用

    原则1:如果遇到的是可中断的阻塞方法, 并抛出 InterruptedException,可以继续向方法调用栈的上层抛出该异常;如果检测到中断,则可清除中断状态并抛出 InterruptedException,使当前方法也成为一个可中断的方法

    原则2:若有时候不太方便在方法上抛出 InterruptedException,比如要实现的某个接口中的方法签名上没有 throws InterruptedException,这时就可以捕获可中断方法的 InterruptedException 并通过 Thread.currentThread.interrupt() 来重新设置中断状态。

    1. 优雅得中断线程

    捕获的InterruptedException并通过 Thread.currentThread.interrupt()来重新设置中断状态

    public class InterruptTest {
    
        public static void main(String[] args) {
            Thread t = new PrintThread();
            t.setName("PrintThread");
            t.start();
            try {
                TimeUnit.SECONDS.sleep(5);
                t.interrupt();
            } catch (InterruptedException e) {
                e.printStackTrace();
                System.out.println(e.getMessage());
            }
    
        }
    
        /**
         * 每隔1s打印一次数据
         */
        static class PrintThread extends Thread {
            private volatile boolean enable = true;
    
            public boolean isEnable() {
                return enable;
            }
    
            public void setEnable(boolean enable) {
                this.enable = enable;
            }
    
            @Override
            public void run() {
                while (enable && !isInterrupted()) {
                    SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
                    System.out.println("run at " + sdf.format(new Date()));
                    try {
                        TimeUnit.SECONDS.sleep(3);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        System.out.println(e.getMessage());
                        System.out
                                .println("PrintThread------Thread isInterrupted=" + Thread.currentThread().isInterrupted());
                        // 再次将中断标志设置为true
                        Thread.currentThread().interrupt();
                        System.out
                                .println("2--PrintThread------Thread isInterrupted=" + Thread.currentThread().isInterrupted());
                    }
                }
            }
        }
    }
    

    注意:sleep()方法抛出 InterruptedException后,中断标识也被清空置为 false,如果在catch没有通过调用th.interrupt()方法再次将中断标识置为true,会导致无限循环,中断线程不成功

    catch中不调用`th.interrupt()`的效果 catch中调用`th.interrupt()`的效果

    参考文献

    朴实的聊聊很多人会误解/不懂的Java并发中断机制

    相关文章

      网友评论

          本文标题:线程中断

          本文链接:https://www.haomeiwen.com/subject/wxcltktx.html