Seems to me that
http://docs.oracle.com/javase/6/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
explains it rather well.
I found it fast via
http://lmgtfy.com/?q=Java+dangers+of+Thread.stop
You've cited part of this, presumably from the Javadocs:
"This method is inherently unsafe. Stopping a thread with Thread.stop causes it to unlock all of the
monitors that it has locked (as a natural consequence of the unchecked ThreadDeath exception
propagating up the stack). If any of the objects previously protected by these monitors were in an
inconsistent state, the damaged objects become visible to other threads, potentially resulting in
arbitrary behavior."
I'm not sure what else you need to know here. This is both normative and complete.
As discussed above in the thread my interest was that -- as this excerpt itself implies -- using Thread.stop merely initiates an exception which is then handled just as any other exception is. So what's special about it? In all of our discussion we seem to have only two characteristics that are special. The first is that ThreadDeath will not normally cause an error message. That seems pretty trivial. The second is that the exception can in principle happen anywhere in the stopped thread. However if it were easy to stop threads only in some TBD safe zone then it seems that using Thread.stop could be done robustly.
Since it seems that most commenters have limited experience with Thread.stop I've played a little with it myself. E.g., a test monitor class creates aset of worker threads. Each worker thread requests a task from the monitor, executes the task, reports the result back to the monitor, then asks forthe next task. The monitor periodically kills all threads older than somearbitrary value and creates a new replacement, caching the task that got cancelled to be rerun. The worker threads are only stoppable during the execution phase. Here's one of the classes:
package threadstoptester;
public class StoppableThread extends Thread {
private volatile boolean isStoppable = false;
private volatile boolean running = true;
synchronized protected void stoppable(boolean flag) {
if (!flag && !running) {
// Don't proceed to nonstoppable state if
// someone has already stopped the thread.
throw new ThreadDeath();
}
isStoppable = flag;
}
synchronized protected boolean running() {
return running;
}
synchronized public boolean doStop() {
if (isStoppable) {
isStoppable = false;
running = false;
this.stop();
return true;
} else {
return false;
}
}
}
The worker threads inherit this class, and the monitor thread calls the doStop method on the appropriate worker thread object which in turn calls Thread.stop
on the appropriate thread if the thread is currently stoppable.
My fairly simple implementation seems to run fine. Note that although it'snot especially complex, in terms of thread interactions this is much more involved than what I would normally do. Generally I just start one thread to do one task and throw it away when it's done. So this seems like a fairtest of whether there are some circumstances we can use Thread.stop robustly.
Of course I haven't proved anything... There could be subtle (or given my multithreading experience, obvious) bugs that just haven't surfaced in my limited testing. I've killed as many as ~40K threads so one might hope problems might emerge. Still so far this is play. But it doesn't suggest thatprograms are necessarily unstable when using Thread.stop, even promiscuously.
So where might this approach be useful:
1. Testing/running code that might include infinite loops due to bugs or user inputs.
- Better if single threaded
- Limited access to code
- Don't want overhead of starting new VM for each test
(or need some level of communication that makes separate VM inconvenient)
2. Stopping out of control tasks in some existing executor framework (e.g.., web server) where we need to clean up wayward threads.
- need to be able to identify 'stoppable' regions which may be hard.
3. As a potentially attractive alternative to the cooperative stopping mechanism in certain cases.
- When substantial code base might be implicated in cooperative approach.
- May require sandbox like approach.
The third alternative (and indeed all three) will be controversial, so I'llclose with an amplification of what I'm thinking there.
The cooperative Thread.interrupt() approach implies that the code that might be interrupted knows about this, i.e., the worker code is aware that there is some monitor. It needs to periodically check the interrupt flag and do something. This couples the invoker to the invoked in a way that's a bit unattractive. It's no big deal if it's just a simple loop to check but if there are lots of classes and methods that need to be instrumented it's not elegant.
If one has a set of code that is running where it's known that the invokingthreads are not affected except in some clearly defined way by the worker threads (e.g. a kind of sandbox), then using Thread.stop potentially decouples the monitor/invoker process from the worker code. In the right circumstances, I can imagine this being more attractive. My limited testing suggests that those circumstances need not be the null set.
That's not to say that others will or should agree with any of this, but thanks to both the user comments and my own explorations, I think I understand the issues much better. I'm intrigued by the responses discussing ways to do this that all the creation of dynamic objects that would be safe even in the presence of Thread.stop -- but that's probably more than I need to worry about now.
Thanks to all.
Regards,
Tom McGlynn