美文网首页多线程
Thread的interrupt中断操作

Thread的interrupt中断操作

作者: virtual灬zzZ | 来源:发表于2022-01-22 15:20 被阅读0次

    线程中断意思

    中断的意思,即给线程附上一个中断的标记,是标记,给个标记只是表明请求终止这个线程,并不是立马就给终止了,具体终止还得靠线程自己。

    线程标记

    关于线程标记,调用某个线程的interrupt方法,即t.interrupt(),就会给当前打上中断标记。

    关于线程中断标记的消除:

    • Thread.interrupted() 静态方法:该方法会判断当前线程是不是被中断标记了,同时会清除该线程的中断标记,这点很重要。

    • 遇上interruptedException:被catch到了,执行里面的代码,并且中断标记会清除。

    • t.isInterrupted():判断t是不是被中断标记了,这个并不会清除中断标记。

    一个例子:

    public class InterruptSignIsClean {
        public static void main(String[] args) {
            Thread carOne = new Thread(() -> {
                long startMills = System.currentTimeMillis();
                while (System.currentTimeMillis() - startMills < 3) {
                    //if (Thread.currentThread().isInterrupted()) {
                    if (Thread.interrupted()) {
                        SmallTool.printTimeAndThread("被中断了还开个毛???");
                    } else {
                        SmallTool.printTimeAndThread("没被中断继续开");
                    }
                }
            });
    
            carOne.start();
    
            SmallTool.sleepMillis(1);
            carOne.interrupt();
             /**
             * 运行结果:
             * (调用Thread.currentThread().isInterrupted())
             * 1641827127303    |   11  |   Thread-0    |   没被中断继续开
             1641827127303  |   11  |   Thread-0    |   被中断了还开个毛???
             1641827127304  |   11  |   Thread-0    |   被中断了还开个毛???
             1641827127304  |   11  |   Thread-0    |   被中断了还开个毛???
             1641827127304  |   11  |   Thread-0    |   被中断了还开个毛???
             1641827127304  |   11  |   Thread-0    |   被中断了还开个毛???
             1641827127304  |   11  |   Thread-0    |   被中断了还开个毛???
             1641827127304  |   11  |   Thread-0    |   被中断了还开个毛???
             1641827127304  |   11  |   Thread-0    |   被中断了还开个毛???
             1641827127304  |   11  |   Thread-0    |   被中断了还开个毛???
             1641827127304  |   11  |   Thread-0    |   被中断了还开个毛???
             1641827127304  |   11  |   Thread-0    |   被中断了还开个毛???
             1641827127304  |   11  |   Thread-0    |   被中断了还开个毛???
             1641827127305  |   11  |   Thread-0    |   被中断了还开个毛???
             *
             *
             * 调用Thread.interrupted()这个静态方法,会清楚中断标志位
             1641827423247  |   11  |   Thread-0    |   没被中断继续开
             1641827423247  |   11  |   Thread-0    |   没被中断继续开
             1641827423247  |   11  |   Thread-0    |   没被中断继续开
             1641827423248  |   11  |   Thread-0    |   没被中断继续开
             1641827423248  |   11  |   Thread-0    |   被中断了还开个毛???
             1641827423248  |   11  |   Thread-0    |   没被中断继续开
             1641827423248  |   11  |   Thread-0    |   没被中断继续开
             1641827423248  |   11  |   Thread-0    |   没被中断继续开
             1641827423248  |   11  |   Thread-0    |   没被中断继续开
             1641827423248  |   11  |   Thread-0    |   没被中断继续开
             1641827423248  |   11  |   Thread-0    |   没被中断继续开
             1641827423248  |   11  |   Thread-0    |   没被中断继续开
             1641827423248  |   11  |   Thread-0    |   没被中断继续开
             */
        }
    }
    

    要点:

    如果调用sleep(timeout)之前或正在sleep的过程中,线程就有了中断标记位,就不会去睡觉了,立马跳到catch(interruptException)执行余下的代码:(注意时间戳)

    sleep之前
    public class BeforehandInterrupt {
        public static void main(String[] args) {
    
            Thread.currentThread().interrupt();
    
            try {
                SmallTool.printTimeAndThread("开始睡眠");
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                SmallTool.printTimeAndThread("发生中断");
            }
    
            SmallTool.printTimeAndThread("结束睡眠");
            /**
             * 运行结果:看时间戳
             * 1641827782934    |   1   |   main    |   开始睡眠
               1641827782934    |   1   |   main    |   发生中断
               1641827782934    |   1   |   main    |   结束睡眠
             *
             */
        }
    }
    
    sleep过程中
    public class ThreadInterrupt {
        public static void main(String[] args) {
    
            Thread carTwo = new Thread(() -> {
                SmallTool.printTimeAndThread("卡丁2号 准备过桥");
                SmallTool.printTimeAndThread("发现1号在过,开始等待");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    SmallTool.printTimeAndThread("卡丁2号 开始过桥");
                }
                SmallTool.printTimeAndThread("卡丁2号 过桥完毕");
            });
    
    
            Thread carOne = new Thread(() -> {
                SmallTool.printTimeAndThread("卡丁1号 开始过桥");
                int timeSpend = new Random().nextInt(500) + 1000;
                SmallTool.sleepMillis(timeSpend);
                SmallTool.printTimeAndThread("卡丁1号 过桥完毕 耗时:" + timeSpend);
                SmallTool.printTimeAndThread("卡丁2号的状态" + carTwo.getState());
                //如果不加这句,carTwo的InterruptedException打印不会触发,而且要等完5秒才打印卡丁2号过桥完毕
                //加上的话,立刻中断并继续执行下去
                carTwo.interrupt();
            });
    
            carOne.start();
            carTwo.start();
        }
        /**
         * 运行结果:
         * (注释carTwo.interrupt,,看前面的时间戳)
         1641822835997  |   12  |   Thread-1    |   卡丁1号 开始过桥
         1641822835999  |   11  |   Thread-0    |   卡丁2号 准备过桥
         1641822835999  |   11  |   Thread-0    |   发现1号在过,开始等待
         1641822837375  |   12  |   Thread-1    |   卡丁1号 过桥完毕 耗时:1375
         1641822837375  |   12  |   Thread-1    |   卡丁2号的状态TIMED_WAITING
         1641822846008  |   11  |   Thread-0    |   卡丁2号 过桥完毕
         *
         * 不注释
         1641824076546  |   12  |   Thread-1    |   卡丁1号 开始过桥
         1641824076548  |   11  |   Thread-0    |   卡丁2号 准备过桥
         1641824076548  |   11  |   Thread-0    |   发现1号在过,开始等待
         1641824077600  |   12  |   Thread-1    |   卡丁1号 过桥完毕 耗时:1050
         1641824077600  |   12  |   Thread-1    |   卡丁2号的状态TIMED_WAITING
         1641824077600  |   11  |   Thread-0    |   卡丁2号 开始过桥
         1641824077601  |   11  |   Thread-0    |   卡丁2号 过桥完毕
         *
         */
    }
    

    关于InterruptedException的抛出

    /**
     * Thrown when a thread is waiting, sleeping, or otherwise occupied,
     * and the thread is interrupted, either before or during the activity.
     * Occasionally a method may wish to test whether the current
     * thread has been interrupted, and if so, to immediately throw
     * this exception.  The following code can be used to achieve
     * this effect:
     * <pre>
     *  if (Thread.interrupted())  // Clears interrupted status!
     *      throw new InterruptedException();
     * </pre>
     */
    public
    class InterruptedException extends Exception
    余下略
    

    可以看到InterruptedException 源码的注释,什么时候抛这个异常?当线程在等待、睡眠或被其他占用的时候,线程被打断,无论在运行之前还是期间,则立马抛出异常。

    比如在调用sleep(timeout)的时候,该线程会处于timed_waiting的状态;Object.wait()就是waiting,其加上timeout参数,就是timed_waiting,上述的注释已经说明清楚。

    无故设置中断标记位

    再者,比如某线程运行得好好的,runnable状态,不会变成waiting、timed_waiting的状态,这时无缘无故给它一个t.interrupt(),其实对它是没有影响的,仅仅给它弄了个中断标记位,并不会影响它执行程序,如果后续有需要对它的中断标记状态做点什么事情,完全就可进行判断其中断标记位来操作。

    相关文章

      网友评论

        本文标题:Thread的interrupt中断操作

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