Interrupt()这个方法是会给当前执行的线程发送一个中断的信号
interrupted() 与isInterrupted() 这两个的作用是一样的,那为什么要一个是静态方法一个非静态方法呢?
Demo
定义一个线程假设他在做一些事情,他启动之后可能还没有真正的运行起来,直接输出打断是不太正确的所以简单的休眠一下。
运行结果:
没有中断前是false,打断后为true。
- 线程一直运行的原因是:还没有捕获到线程被中断的信息,或者说通过线程被中断会抛出异常但是没有任何异常捕获的语句。
那怎么做呢?先看下Api文档
根据文档说要使用那几个方法后会捕获到InterruptedException异常,如果没有使用到呢?
尝试在循环里面输出一下:
运行结果:
结果显示还是有这样的信号,并不是说只有在线程里面有那几个方法的时候他才会收到。
Interrupt源码
如果不是当前线程自我中断,会先做一次权限检查。如果被中断的线程属于系统线程组(即JVM线程),checkAccess()方法会使用系统的System.getSecurityManager()来判断权限,如果权限不允许会抛出SecurityException。由于Java默认没有开启安全策略,此方法其实会跳过安全检查。
blockerLock 是他自己定义的一个锁
- Interruptible b = blocker; 这个是怎么传的呢?
- interrupt0(); 他是不管刚才读文档说的“有没有那三种类型的方法去调用,他都会被interrupt status去进行设置”
- 所以说我们这边只是没有任何方法捕获到他的这个异常,才退不出来。
sleep()的打断方式
改为:
运行结果:
收到打断信息,休眠状态被打断,线程收到信号之后,他还在运行,还在死循环里面。
wait()的打断方式
已经看了interrupted() 与isInterrupted() 这两个方法,通过sleep的方式去打断他。
接下里来看一下wait()的方式。
wait()是Object的一个方法,不是线程特有的方法,那怎么去做呢?
使用wait()方法的时候必须给一个monitor,这个monitor必须是用synchronized去进行包装。
运行结果:
中断信号收到,同时也被捕获了,没有退出的原因是死循环任务没有完成。
调用之前比较老的方法可以吗?
确实是可以的,但是会有严重的问题,这个方法在很多版本以前就不让用了,建议千万不要使用。
看到Api里已经有实例方法isInterrupted() 去判断了,为什么还要有一个类方法interrupted() 呢,而且做的事情还是完全一样的。
那他到底是做什么的呢?
在这个方法里面可以看自己是否被中断了 (调用Thread的实例方法)
上图所示定义了一个t,里面复写了run()方法,这边是可以这样去用的,那如果线程不是这样定义的,而是这样定义的怎么办的呢?
一样是复写run()方法,但是这里不能在使用isInterrupted()了,必须去调Thread.interrupted()
Thread.interrupted()拿到的也是当前线程t
isInterrupted()与interrupted()的源码
如图所示两个调用的都是同一个东西
这个就是有个实例方法和类方法要做的事情是一样的。
join()的打断方式
这里调用join()方法后,就会抛出这个异常到这里吗?
肯定是不会的因为应该还有其他线程去打断她。
还要写一个线程,因为程序运行到这里会 block 住。
线程t2休眠100毫秒,然后把t打断,主要是看下join那边会不会抛异常。
这里的t是final修饰的,Java8中对这个语法团可以不进行显示的声明。
运行结果:
执行完后并没有被打断,之前的 t.interrupt();不管是sleep()还是wait()都会打断,但是这里是为什么呢?
分析:
- sleep时是当前线程t,然后做t的打断没问题。
- wait时是当前线程t,然后做t的打断没问题。
- join时是main线程,然后打断的是t线程。
干掉main线程()
运行结果:
其实join()里面用的还是有用wait()方法做了一下。
大家一定要会去分析,运行过程中不一定是那一个线程。
这些小技巧在后面会非常有用,尤其是当用t.stop()停止不了线程时。