Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to abort a thread in a fast and clean way in java?

Here is my problem: I've got a dialog with some parameters that the user can change (via a spinner for example). Each time one of these parameters is changed, I launch a thread to update a 3D view according to the new parameter value. If the user changes another value (or the same value again by clicking many times on the spinner arrow) while the first thread is working, I would like to abort the first thread (and the update of the 3D view) and launch a new one with the latest parameter value.

How can I do something like that?

PS: There is no loop in the run() method of my thread, so checking for a flag is not an option: the thread updating the 3D view basically only calls a single method that is very long to execute. I can't add any flag in this method asking to abort either as I do not have access to its code.

like image 230
jumar Avatar asked Sep 18 '08 16:09

jumar


People also ask

How do you stop a thread immediately?

Whenever we want to stop a thread from running state by calling stop() method of Thread class in Java. This method stops the execution of a running thread and removes it from the waiting threads pool and garbage collected. A thread will also move to the dead state automatically when it reaches the end of its method.

How do you clear a thread in Java?

Java Thread destroy() methodThe destroy() method of thread class is used to destroy the thread group and all of its subgroups. The thread group must be empty, indicating that all threads that had been in the thread group have since stopped.

How do you stop a specific thread in Java?

You can store each thread's reference into a HashMap - along with its id or Name as the key. Later when you want to deal with one particular Cashier thread , use the Name or id to fetch the corresponding Thread from the HashMap and call the appropriate logOff() method on it.

Which method is used to terminate a thread in Java?

stop() method is used to terminate the thread execution. Once thread executed is halted by stop() method, start() function cannot restart the thread execution. stop() function has been deprecated in the latest versions of java.


3 Answers

Try interrupt() as some have said to see if it makes any difference to your thread. If not, try destroying or closing a resource that will make the thread stop. That has a chance of being a little better than trying to throw Thread.stop() at it.

If performance is tolerable, you might view each 3D update as a discrete non-interruptible event and just let it run through to conclusion, checking afterward if there's a new latest update to perform. This might make the GUI a little choppy to users, as they would be able to make five changes, then see the graphical results from how things were five changes ago, then see the result of their latest change. But depending on how long this process is, it might be tolerable, and it would avoid having to kill the thread. Design might look like this:

boolean stopFlag = false; Object[] latestArgs = null;  public void run() {   while (!stopFlag) {     if (latestArgs != null) {       Object[] args = latestArgs;       latestArgs = null;       perform3dUpdate(args);     } else {       Thread.sleep(500);     }   } }  public void endThread() {   stopFlag = true; }  public void updateSettings(Object[] args) {   latestArgs = args; } 
like image 56
skiphoppy Avatar answered Oct 04 '22 10:10

skiphoppy


The thread that is updating the 3D view should periodically check some flag (use a volatile boolean) to see if it should terminate. When you want to abort the thread, just set the flag. When the thread next checks the flag, it should simply break out of whatever loop it is using to update the view and return from its run method.

If you truly cannot access the code the Thread is running to have it check a flag, then there is no safe way to stop the Thread. Does this Thread ever terminate normally before your application completes? If so, what causes it to stop?

If it runs for some long period of time, and you simply must end it, you can consider using the deprecated Thread.stop() method. However, it was deprecated for a good reason. If that Thread is stopped while in the middle of some operation that leaves something in an inconsistent state or some resource not cleaned up properly, then you could be in trouble. Here's a note from the documentation:

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. Many 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. If the target thread waits for long periods (on a condition variable, for example), the interrupt method should be used to interrupt the wait. For more information, see Why are Thread.stop, Thread.suspend and Thread.resume Deprecated?

like image 22
Dave L. Avatar answered Oct 04 '22 11:10

Dave L.


Instead of rolling your own boolean flag, why not just use the thread interrupt mechanism already in Java threads? Depending on how the internals were implemented in the code you can't change, you may be able to abort part of its execution too.

Outer Thread:

if(oldThread.isRunning())
{
    oldThread.interrupt();
    // Be careful if you're doing this in response to a user
    // action on the Event Thread
    // Blocking the Event Dispatch Thread in Java is BAD BAD BAD
    oldThread.join();
}

oldThread = new Thread(someRunnable);
oldThread.start();

Inner Runnable/Thread:

public void run()
{
    // If this is all you're doing, interrupts and boolean flags may not work
    callExternalMethod(args);
}

public void run()
{
    while(!Thread.currentThread().isInterrupted)
    {
        // If you have multiple steps in here, check interrupted peridically and
        // abort the while loop cleanly
    }
}
like image 24
basszero Avatar answered Oct 04 '22 09:10

basszero