为什么废弃stop()?
java里线程停止有一个方法,叫stop(),但是很早就被废弃了,因为会导致很多问题。比如下面一种case:
假设这样一种情况,有三个线程,分别为Thread1,Thread2,Thread3。
此时Thread1暂停,但是仍然持有内存锁,Thread1是否被恢复也不知道,而Thread3想要读取内存,只能等待,如果此时Thread1等待了Thread3的锁,那就会变成死锁了,这也是一个严重的问题。
如果此时情况变化了,Thread1被停止,立即释放内存锁,Thread3会立即获得锁,内存根本没有清理的机会(原来Thread1数据写一半,突然被干掉了,内存还没有被清理干净),就被Thread3读取了,而Thread3读到的也是一个莫名其妙的数据。
应该如何停止线程?
我们目的是让线程里的任务结束,任务结束,线程会自动停止,并处理自己的烂摊子,如果强制stop的话,谁处理烂摊子?
- 通知目标线程自行结束,而不是强行停止
- 目标线程应当具备处理终端的能力
- 中断方式:Interrupt 和 boolean 标志位
interrupt方式
1、原生支持的情况,如果调用sleep()方法,会要求加上try-catch,来捕获中断异常。
如果调用interrupt() 会走到异常位置,在捕获异常出可以进行处理终止线程,但是有些情况并不支持原生的interrupt,例如:
此时调用interrupt() ,而线程没有任何感觉,那么怎么办呢?
用interrupted()来进行判断,是否发生了中断。
interrupted() 与 isInterrupted()区别:
- interrupted() 是静态方法
- 获取的是当前运行的线程
- 中断状态调用后清空,重复调用后续返回false
- isInterrupted() 是非静态方法
- 调用的是线程对象对应的线程
- 可重复调用,中断清空前一直返回true
我们看下底层源码,调用的是c++的程序
首先是找到的对象不一样,其次分别调用的是Interrupted()和isInterrupted()
不同的就是多了一行代码,清空当前的中断状态。具体状态值是被加了锁,保证读的时候是线程安全的。
Boolean标注位
这个比较简单了,用一个标志位,此时注意的是,为了保证线程间内存可见性的问题,需要加上volatile来修饰
最后总结一下,interrupt与Boolean本质上是一致的,都是一个标志位,只不过interrupt对标志位加了锁,并且用的是jni方式,因此使用interrupt会对性能有一点点影响。