美文网首页多线程
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