如下是官方文档,先贴上,抽时间翻译
Why Are
|
Why is Thread.stop
deprecated?
Because it is inherently unsafe. Stopping a thread causes it to unlock all the monitors that it has locked. (The monitors are unlocked as the ThreadDeath
exception propagates up the stack.) If any of the objects previously protected by these monitors were in an inconsistent state, other threads may now view these objects in an inconsistent state. Such objects are said to be damaged. When threads operate on damaged objects, arbitrary behavior can result. This behavior may be subtle and difficult to detect, or it may be pronounced. Unlike other unchecked exceptions, ThreadDeath
kills threads silently; thus, the user has no warning that his program may be corrupted. The corruption can manifest itself at any time after the actual damage occurs, even hours or days in the future.
为什么thread.stop被废弃了呢?
因为它是天生不安全的。停止一个线程会导致它解锁它所锁定的所有monitor(当一个ThreadDeath Exception沿着栈向上传播时会解锁monitor),如果这些被释放的锁所保护的objects有任何一个进入一个不一致的状态,其他将要访问该objects的线程也会以一种不一致的状态来访问这些objects。这种objects称为“被损坏了”。当线程对被损坏的objects上做操作时,可能会产生意想不到的结果,这些行为可能是很严重的,并且难以探测到,
不像其他 uncheck exception,ThreadDeath Exception静默的杀死进程,因此,用户不会被警告他的程序会崩溃,这会在“损坏”之后的任何时候发生,甚至几小时或者几天后。
Couldn't I just catch the ThreadDeath
exception and fix the damaged object?
In theory, perhaps, but it would vastly complicate the task of writing correct multithreaded code. The task would be nearly insurmountable for two reasons:
- A thread can throw a
ThreadDeath
exception almost anywhere. All synchronized methods and blocks would have to be studied in great detail,with this in mind. - A thread can throw a second
ThreadDeath
exception while cleaning up from the first (in thecatch
orfinally
clause). Cleanup would have to repeated till it succeeded. The code to ensure this would be quite complex.
In sum, it just isn't practical.
我不能catch到这个ThreadDeath
exception 然后修复被损坏的object吗
理论上,或许可以。但是它会极大地将多线程代码编写复杂化,以下两个原因,让这项工作变得几乎不可能完成:
1.一个线程会在几乎任何地方抛出ThreadDeath
exception,考虑到这一点,所有的同步方法和代码块将必须进行详细的考察
2.线程可能在处理第一个异常的时候(在catch,finally语句块里)抛出第二个异常,处理语句必须将不得不重新开始反复如此直到成功,来保证这一过程的代码将会非常复杂。
总结一下,这是不切实际的。
What about Thread.stop(Throwable)
?
In addition to all of the problems noted above, this method may be used to generate exceptions that its target thread is unprepared to handle (including checked exceptions that the thread could not possibly throw, were it not for this method). For example, the following method is behaviorally identical to Java's throw
operation, but circumvents the compiler's attempts to guarantee that the calling method has declared all of the checked exceptions that it may throw:
static void sneakyThrow(Throwable t) { Thread.currentThread().stop(t); }
那么Thread.stop()方法是怎么回事?
除了上边提到的这些问题之外,这个方法会产生它的目标线程未准备好处理的异常(包括Checked exception,这种线程或许不会抛出的异常),例如,下面的方法在行为上是与java的 Throwoperation相同的,但是规避了编译器试图保证该调用方法已经声明了所有的它可能会抛出的所有Checkd Exception的行为。
static void sneakyThrow(Throwable t) { Thread.currentThread().stop(t); }
What should I use instead of Thread.stop
?
Most uses of stop
should be replaced by code that simply modifies some variable to indicate that the target thread should stop running. The target thread should check this variable regularly, and return from its run method in an orderly fashion if the variable indicates that it is to stop running. (This is the approach that the Java Tutorial has always recommended.) To ensure prompt communication of the stop-request, the variable must be volatile (or access to the variable must be synchronized).
For example, suppose your applet contains the following start
, stop
and run
methods:
如果不用Thread.stop(),我们应该使用什么方法?
大多数对stop方法的调用应该用指示目标线程是否应该停止运行的一些变量的简单代码来替换,目标线程应该定时的检查这些变量,当发现这些变量指示该线程应该停止运行时,有序地从它的run方法来return。(这是java tutorial中经常要求的方式)
private Thread blinker; public void start() { blinker = new Thread(this); blinker.start(); } public void stop() { blinker.stop(); // UNSAFE! } public void run() { Thread thisThread = Thread.currentThread(); while (true) { try { thisThread.sleep(interval); } catch (InterruptedException e){ } repaint(); } }You can avoid the use of
Thread.stop
by replacing the applet's
stop
and
run
methods with:
private volatile Thread blinker; public void stop() { blinker = null; } public void run() { Thread thisThread = Thread.currentThread(); while (blinker == thisThread) { try { thisThread.sleep(interval); } catch (InterruptedException e){ } repaint(); } }
How do I stop a thread that waits for long periods (e.g., for input)?
That's what the Thread.interrupt
method is for. The same "state based" signaling mechanism shown above can be used, but the state change (blinker = null
, in the previous example) can be followed by a call to Thread.interrupt
, to interrupt the wait:
public void stop() { Thread moribund = waiter; waiter = null; moribund.interrupt(); }For this technique to work, it's critical that any method that catches an interrupt exception and is not prepared to deal with it immediately reasserts the exception. We say reasserts rather than rethrows , because it is not always possible to rethrow the exception. If the method that catches the
InterruptedException
is not declared to throw this (checked) exception, then it should "reinterrupt itself" with the following incantation:
Thread.currentThread().interrupt();This ensures that the Thread will reraise the
InterruptedException
as soon as it is able.
What if a thread doesn't respond to Thread.interrupt
?
In some cases, you can use application specific tricks. For example, if a thread is waiting on a known socket, you can close the socket to cause the thread to return immediately. Unfortunately, there really isn't any technique that works in general. It should be noted that in all situations where a waiting thread doesn't respond to Thread.interrupt
, it wouldn't respond to Thread.stop
either. Such cases include deliberate denial-of-service attacks, and I/O operations for which thread.stop and thread.interrupt do not work properly.