我之前只是知道有两种做法
- while 一个 flag ,通过控制 flag
- 另一个就是
Thread::intercept()
,加try ... catch
好吧实际工作里基本没有 kill 线程的经验,现在来看看
主要是 interrupt ,因为 while 方法其实算不上什么停止线程,当 while 内的代码块阻塞了,根本走不到下一次 flag 判断。
直接看源码里的注释:
https://developer.android.com/reference/java/lang/Thread.html#interrupt()
- 首先会进行检查是否拥有修改当前线程的权限,权限异常会抛出 SecurityException
- 调用 interrupt ,如果此时线程阻塞在 Object class 的 wait(), wait(long)), or wait(long, int) 方法 , 或是当前 class 的 join(), join(long), join(long, int), sleep(long), or sleep(long, int)方法,会清除线程 interrupt 状态,并抛出 InterruptedException.
- 调用 interrupt ,如果此时线程阻塞在一个 InterruptibleChannel 的 I/O 操作上,channel 将会被关闭,设置线程的 interrupt 状态,线程收到 ClosedByInterruptException
- 调用 interrupt ,如果此时线程 block 在一个 Selector,会立即设置线程的 interrupt 状态,并从 selection 操作中返回,也许返回一个非零值,就像执行 selector 的 wakeup 方法一样。
- 调用 interrupt ,如果以上情况都不是,会设置线程的 interrupt 状态
直接看第二条和第五条
第 2 条说的是阻塞在这些个方法时调用 interrupt 会抛出 InterruptedException ,这就是我们为啥要加 try ... catch
然后第 5 条,如果以上几条 case 都不是,调用 interrupt 只会设置线程的 interrupt status……(好像知道面试为啥挂了
1 | // https://stackoverflow.com/a/10962613/4097210 |
再翻译一下这个 Stack Overflow 的回答
Q: https://stackoverflow.com/questions/10961714/how-to-properly-stop-the-thread-in-java
A: https://stackoverflow.com/a/10962613/4097210
Thread.interrupt()
是个不错的方法。如果你的代码处于可中断的阻塞调用 (比如 Thread.sleep
或是使用 java.nio Channel 操作),你可以从中立即退出。
如果使用 flag,只能等这段阻塞代码跑完,再次进入 flag condition 判断时终止。但有些情况不得不用这个方法,比如使用标准 InputStream
/OutputStream
api 时,它不是 interruptable 的。
这种情况,调用 interrupt 并不会终止 IO,但是你可以在代码(可以安全 stop 线程并清理资源的位置)加上这么一句话:
1 | if (Thread.currentThread().isInterrupted()) { |
就像我上面说的 Thread.interrupt()
的优势在于可以立即退出,flag 无论如何做不到这点。