原理介绍
使用interrupt来通知,而不是强制。
如何正确的停止线程
- 通常线程会在什么情况下停止
run方法执行完毕;出现异常且未捕获; - 正确的停止方法:interrupt请求停止线程
- 通常情况(run方法内没有sleep或wait等会造成阻塞的方法)
通过thread.interrupt()中断线程,然后通过Thread.currentThread().isInterrupted()判断是否中断线程。 - 线程可能阻塞
阻塞时用interrupt停止线程是通过抛出InterruptedException来停止注:在抛出InterruptedException后会清除掉Thread.currentThread().isInterrupted()标记位。
- 在while内try/catch会无法停止,需要包住while
- 实际开发中两种最佳实践
- 优先选择:传递中断。
将出现的InterruptedException不用try/catch处理,而是传递给run方法处理。
- 不想或者无法传递:恢复中断。在捕获InterruptedException的catch语句中通过Thread.currentThread().interrupt()重新设置中断。
不应该屏蔽中断:即不应该既不将异常传递给run方法也不重新设置中断。
- 响应中断的方法
- Object.wait()常用
- Thread.sleep()常用
- Thread.join()常用
- java.util.concurrent.BlockingQueue.take()/put(E)阻塞队列
- java.util.concurrent.locks.Lock.lockInterruptibly()锁
。。。
错误的停止方法
- stop()方法:已过时。该方法具有固定的不安全性。用 Thread.stop() 来终止线程将释放它已经锁定的所有监视器。会导致线程运行一半突然停止,没办法完成一个基本单位的操作,造成脏数据。
- suspend和resume:挂起不会释放锁,容易造成死锁。
- volatile boolean变量控制停止:待停止的线程内部发生了阻塞会导致volatile变量无法停止线程。
停止线程相关重要函数
- static boolean interrupted():检测当前线程是否被中断,会清除线程中断状态
- boolean isInterrupted():同上,调用同一个函数,但是不会清除线程中断状态。
- Thread.interrupted():看调用该语句的线程是否中断。
面试题:
- 如何停止线程:
- 原理:用interrupt来请求。可以保证数据安全而且适用于阻塞场景。
- 一个线程调用interrupt,被中断的线程配合:请求方发出请求信号、被停止方检查中断信号并在可能出现InterruptedException的地方处理信号、子方法被调用方向上抛出异常或者再次设为中断状态。
- 错误:stop/suspend过时:数据安全与死锁。volatile的boolean无法处理长时间阻塞的情况。
- 如何处理不可中断阻塞
没有通用方法,针对不同的场景使用不同的方法