原文:《Java Thread Primitive Deprecation》
为什么 Thread.stop 被废弃了?
Thread.stop 不安全。
-
Stop 一个线程会导致它释放所持有的锁(monitor)。(ThreadDeatch 抛出后会释放 monitor 的锁。)
-
这可能会导致之前被 monitor 保护的对象处于 不一致的状态,并被其它线程看到。也就是说,这些 对象被损坏 了。
-
线程操作被损坏的对象会导致不可预料的行为。
-
这些行为可能很微妙难以被察觉,也可能非常明显。与其它异常不同的是,ThreadDeatch 异常会悄悄地杀掉线程,用户感知不到程序已被损坏。这种程序损坏可能在错误发生后任何时候显现,甚至是几小时、几天。
为什么 我不能捕获 ThreadDeath 异常,并修复损坏的对象?
理论上,也许是可以的。但这会使编写多线程任务代码非常复杂,几乎不可能实现。因为:
-
线程可能在任何地方抛出 ThreadDeath 异常。必须非常详尽地分析所有同步方法和代码块,来处理这些情况。
-
线程在处理第一个 ThreadDeath 异常期间(catch 或 finally),可能会再次抛出 ThreadDeath 异常(嵌套异常)。你的异常处理操作必须不断重复,直到成功。这会导致代码非常复杂。
所以这种方案是不切实际的!
Thread.stop(Throwable) 如何?
上述提到的所有问题它都有。此外,此方法一般用于生成一个 目标线程未准备好处理的 异常(包括目标线程不可能抛出的一些 受检异常)。如,以下示例中方法的行为等价于 throw 操作,但它规避了编译器对受检异常的检查保障 —— 调用方法必须声明所有可能抛出的受检异常。
(即,这是一种不安全的错误代码模式。)
Java代码
-
void sneakyThrow(Throwable t) {
-
Thread.currentThread().stop(t);
-
}
我该用什么方法替代 Thread.stop ?
绝大多数使用 stop 的代码应改为:
-
修改一些标记性变量的值 以指示目标线程应停止运行;
-
目标线程应定期检查这些标记变量;当检测到变量值指示应停止运行时,再有条不紊地从运行方法中自行返回。
-
为了保证“停止请求”通信正确,此标记变量必须是 volatile 或 对其访问操作进行同步。
示例:假设你的程序中有以下三个方法 start、stop、run。
Java代码