线程中断 interrupt()

interrupt()是什么?

	interrupt是Thread实例为我们提供的方法,通过这个方法可以向线程发出中断信号

为什么要中断?

	作为一个设计良好的线程类,在编写每行代码时必须考虑特殊情况,其中一项就是中断
	中断的原因线程本身并不清除,但为了多线程协作编程,当收到中断信号时如何处理就
	成为我们线程类编写中必修的一门功课

与stop()方法有何异同?

	早期JAVA版本中,对线程提供了stop()方法,它的作用是终止线程的运行。它是个刺客
	不告知理由,不选择时间地点,上来就干死你。
	这种粗暴的行为,通常带来的后果就是资源无法释放,死锁等等

	因此,interrupt方法的出现,变得温柔体贴。它只会通知线程中断而并非终止,此外线
	程最终是什么状态仍旧由线程本身决定。换句话说,通知了线程中断,但是线程不鸟你
	那相当于没有发生任何事情,中断信号也将被丢弃

情景一:检测中断信号并跳出代码段

        Thread singleThread = new Thread(new Runnable() {
            @Override
            public void run() {
                //正常运行中
                while (!Thread.currentThread().isInterrupted()){
                    System.out.println("It is run with Runnable");
                }
                System.out.println("It is interrupted");
            }
        }) ;
        singleThread.start();
        Thread.sleep(5000);
        singleThread.interrupt();

启动线程后,主线程休眠2秒之后,发出interrupt信号
线程内判定interrupt信号,为true时终止while循环后输出最后的日志

效果

It is run with Runnable
It is run with Runnable
It is run with Runnable
It is run with Runnable
It is run with Runnable
It is interrupted

Process finished with exit code 0

情景二:多处检测中断信号

        Thread singleThread = new Thread(new Runnable() {
            @Override
            public void run() {
                //正常运行中
                while (!Thread.currentThread().isInterrupted()){
                    System.out.println("It is run with Runnable A");
                }
                System.out.println("It is interrupted A");

                //如果发生中断,永远都不会走到这里
                while (!Thread.currentThread().isInterrupted()){
                    System.out.println("如果发生中断,永远都不会走到这里");
                }
                System.out.println("直接走到了这里");
            }
        }) ;
        singleThread.start();
        Thread.sleep(5000);
        singleThread.interrupt();

代码中有两个循环,均对中断信号做了检测。如果发生中断事件,第一个循环检测到并跳出了代码段。第二个循环继续检测信号,于是循环都没有进入直接跳出了代码段。

效果

It is run with Runnable A
It is run with Runnable A
It is run with Runnable A
It is run with Runnable A
It is interrupted A
直接走到了这里

情景三:检测信号后重置信号

        Thread singleThread = new Thread(new Runnable() {
            @Override
            public void run() {
                //正常运行中
                /**
                 * 这个是interrupted方法源码
                 public static boolean interrupted() {
                 return currentThread().isInterrupted(true);
                 }
                 */
                while (!Thread.interrupted()){
                    System.out.println("It is run with Runnable A");
                }
                System.out.println("It is interrupted A");

                while (!Thread.currentThread().isInterrupted()){
                    System.out.println("发生中断但被重置了,会走到这里");
                    //为了演示,我们直接跳出去
                    break;
                }
                System.out.println("最后走到了这里");
            }
        }) ;
        singleThread.start();
        Thread.sleep(5000);
        singleThread.interrupt();

静态方法interrupted() :它会检测中断信号并将其重置
在第一个循环内,我们使用Thread.interrupted()进行对中断信号的判定,效果与Thread.currentThread().isInterrupted()一致。唯一不同的就是它判定之后,会将中断信号重置,也就是说下次再判定中断信号时,将是false。于是第二个循环也会正常进入。【为了演示我们主动break跳出】

效果

It is run with Runnable A
It is run with Runnable A
It is run with Runnable A
It is run with Runnable A
It is run with Runnable A
It is run with Runnable A
It is run with Runnable A
It is interrupted A
发生中断但被重置了,会走到这里
最后走到了这里

情景四:检测代码块内存在InterruptedException

        Thread singleThread = new Thread(){
            @Override
            public void run() {
                //正常运行中
                while (!isInterrupted()){
                    try {
                        sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println("即便发了中断信号,也检测了中断信号,还是中断不了");
                    //为了演示搞个随机数跳出
                    if (Math.random()>0.8){
                        break;
                    }
                }
            }
        } ;
        singleThread.start();
        Thread.sleep(5000);
        singleThread.interrupt();

按照之前的写法,发生中断信号后,代码段将跳出,循环将终止。但在本情景下,检测中断的代码块内存在InterruptedException异常,这个异常如果不做处理,那么中断信号将被丢弃,不会真的中断线程

效果

即便发了中断信号,也检测了中断信号,还是中断不了
java.lang.InterruptedException: sleep interrupted
即便发了中断信号,也检测了中断信号,还是中断不了
	at java.lang.Thread.sleep(Native Method)
	at com.weiyinggo.study.CreateThread$1.run(CreateThread.java:25)
即便发了中断信号,也检测了中断信号,还是中断不了
即便发了中断信号,也检测了中断信号,还是中断不了

Process finished with exit code 0

为了解决这种问题,我们需要在异常catch段再次主动中断线程才可以

        Thread singleThread = new Thread(){
            @Override
            public void run() {
                //正常运行中
                while (!isInterrupted()){
                    System.out.println("已经检测到了中断信号");
                    try {
                        sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                        interrupt();
                    }
                    System.out.println("已经再次进行了中断");
                }
            }
        } ;
        singleThread.start();
        Thread.sleep(5000);
        singleThread.interrupt();
///
已经检测到了中断信号
已经再次进行了中断
已经检测到了中断信号
已经再次进行了中断
已经检测到了中断信号
java.lang.InterruptedException: sleep interrupted
已经再次进行了中断
	at java.lang.Thread.sleep(Native Method)
	at com.weiyinggo.study.CreateThread$1.run(CreateThread.java:26)

Process finished with exit code 0

总结

  1. 编写线程类时要时刻考虑各种外来情况,比如本文中的interrupt
  2. 当线程中断检测代码块中存在InterruptedException时要再次主动中断,否则中断信号将被丢弃
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值