Java kill or terminate a thread - java

Hi all:
Basically I need to kill or stop a thread running when user press a Terminate button. This thread loop through a arraylist and display each event on JTextArea. The requirement is when user press the Terminate button, I need to terminate the running thread and at the same time ADD a new "Terminating" event to the arraylist and let it run again to print "Programing terminating". The following code kind of "works", but I got a java.util.ConcurrentModificationException in the console. Anyone can help?
public void startEvents()
{
terminate = false;
worker = new Thread(new Runnable()
{
public void run()
{
Iterator<Event> it = eventList.iterator();
while (it.hasNext())
{
waitWhileSuspended();
terminatEvents();
Event ev = it.next();
try
{
Thread.sleep(ev.getDelayTime());
} catch (InterruptedException e1)
{
e1.printStackTrace();
}
jTextArea.append(ev.toString() + "\n");
it.remove();
}
jbStart.setEnabled(true);
jmiStart.setEnabled(true);
jbRestart.setEnabled(true);
jmiRestart.setEnabled(true);
}
});
worker.start();
}
public void terminatEvents()
{
while(terminate)
{
Thread.yield();
eventList.clear();
eventList.add(new Terminate(delayTime));
startEvents();
}
}

The issue is that you are modifying a List and at the same time looping over it. With standard Lists the behaviour of this is undefined and this throws the Exception.
Have a look at the java.util.concurrent package for collections that are safe for multi threaded use.

It looks like you are modifying the list (clearing it then adding a new Terminate event) while iterating on it. That's why you get the ConcurrentModificationException.
I would advise you to simply have a terminate() method in your thread object, and call it to stop printing event the list THEN print the new Terminate event, without using the list.

You have a changing of Collection from 2 threads. By default, collections are unsynchronized, you should use "Synchronized" keyword or switch to synchronizedCollection http://download.oracle.com/javase/1.4.2/docs/api/java/util/Collections.html#synchronizedCollection(java.util.Collection)

The usual way to stop a thread is to set some volatile boolean flag, I see that in your case it is the terminate field. To follow the normal pattern, you should just check this flag on each iteration like while (!terminated && ...). The thread that sets the terminate flag should also put your final event in some field, say, terminateEvent which you should check after the loop if terminate is true at that point (that is, if the thread was terminated as opposed to finishing normally). Of course, access to terminateEvent should be synchronized (note that volatile probably won't work here).
However, since you have a list of events to process, I would rather follow another pattern. Replace the list with a concurrent queue (LinkedBlockingQueue is a good example) and then, when you need to terminate the thread, instead of setting a boolean flag you just clear the queue and put your termination event there. The event processing thread, after processing each event, should check if that was a termination event (by using instanceof or some sort of getEventClass() method) and if it was, just break the loop.
Note that since your thread has lengthy operations like Thread.sleep() and possibly waitWhileSuspended() (whatever it is, although you may not need it any more after switching to a blocking queue), you need to interrupt() your thread after placing the termination event into the queue, and handle InterruptedException in the event processing thread accordingly to the application logic. For example, you should decide whether to process an event if Thread.sleep() was interrupted or maybe continue to the next iteration instead.

The way I would do it is
public void run() {
while (!isInterrupted()) {
// actual working code goes here
}
} // end of life for this thread
and then just call interrupt() when I want to stop the thread.

Related

How to stop a thread if one thread has completed a task first?

You have to find a file from your two drives of computer. If one thread found it first then the second thread will stop.
Have all threads periodically check a flag variable to see if it's been set and then stop searching if it has. You could do this check after each file, after each directory, or if it's been more than a second since the last time you checked, the mechanics are up to you, depending on your needs.
Then just have a thread set that flag if it finds the file. The other threads will soon pick it up and stop as well.
I prefer having each thread responsible for its own resource, including its lifespan, that's why I prefer this sort of solution to trying to kill a thread from outside it.
I don't know whether Java suffers from the same issues as pthreads (in terms of destroying threads that hold critical resources) but I'd rather be safe than sorry.
The first thing is, you cannot force a thread to stop in java. To stop a thrad safely it has to terminate "naturally". (Means, all the code inside has to be executed or an exception occurs which is not caugth).
In Java you can use the "interrupt" flag. Have both you threads check Thread.currentThread().isInterrupted() like this:
try {
while(!Thread.currentThread().isInterrupted()) {
[...]
Thread.sleep(); //May be you need to sleep here for a short period to not produce to much load on your system, ?
}
} catch (InterruptedException consumed) {
}
So the easiet implementation would be to have your two threads have a reference to one another and if one thread found the file it calls interrupt on the other thread which in turn terminates because of the above while loop.
For more information look Java Concurrency in practice.
You can try to use a flag whether the file was found. The thread will exit if the flag changes its state.
Example with an implemented Runnable
public class Finder implements Runnable {
private static boolean found = false;
#Override
public void run() {
for (ITERATE_THROUG_FILES) {
if (found) {
break;
}
if (FILE == SEARCHED_FILE) {
found = true;
}
}
}
}

Do I have to use thread.interrupted()?

I am writing a GUI for a program that takes some inputs and runs an algorithm on them. The code for the algorithm is fairly long and complex so I have just been launching a new thread from the GUI in order to perform the computations on the inputs.
//algorithmThread previously initialized
if(e.getSource() == startButton) {
if(update.updateStrings(textFields)) {
algorithmThread.start();
}
}
We want to add functionality that will allow the user to stop the computation (it runs for about half an hour on my laptop before producing a result) in the case that they have provided the wrong input files. This is how I am handling that.
else if(e.getSource() == stopButton) {
//if the user presses the stop button then intterupt the
//thread running the algorithm
algorithmThread.interrupt();
System.out.println("algorithm stopped"); //debugging code
//recreate the thread in case the user hits the start button again
algorithmThread = new Thread() {
public void run() {
runNOC();
}
};
}
The program does successfully stop the algorithm(although I think I should do some exception handling), allow the user to enter new input, and restart. My question is, under what conditions would I have to check Thread.interrupted() in the code for the algorithm? Is it necessary/best practice? Or is it acceptable to stop a thread in the manner illustrated above?
All the Thread.interrupt() method does is set an "interrupted" flag, so stopping a thread in this manner requires its cooperation. For example, the algorithm should poll the interrupt status every once in a while, for example once per iteration. You can see an example of this in the Java concurrency tutorial.
Since you are working with a GUI, you may find it easier to run the background thread using a SwingWorker. This class has many features convenient for GUI programming, like updating the GUI when the computation has finished using the done method and canceling the computation without using Thread.interrupt(). Canceling in this manner still requires cooperation from the thread, but is safer because interrupting a thread causes an InterruptedException to be thrown in some situations, such as when the thread is sleeping in Thread.sleep or waiting on a lock in Object.wait.
interrupt is not always evil following this thread:
Is Thread.interrupt() evil?
Around here, we use this method in one specific place: handling
InterruptedExceptions. That may seem a little strange but here's what
it looks like in code:
try {
// Some code that might throw an InterruptedException.
// Using sleep as an example
Thread.sleep(10000);
}
catch (InterruptedException ie) {
System.err.println("Interrupted in our long run. Stopping.");
Thread.currentThread().interrupt();
}
This does two things for us:
It avoids eating the interrupt exception. IDE auto-exception handlers
always provide you with something like ie.printStackTrace(); and a
jaunty "TODO: Something useful needs to go here!" comment.
It restores
the interrupt status without forcing a checked exception on this
method. If the method signature that you're implementing does not have
a throws InterruptedException clause, this is your other option for
propagating that interrupted status.

is this the correct way to 'stop' a thread gracefully?

instead of continuous checking of variable inside a loop:
class Tester {
public static void main() {
Try t = new Try();
Thread.sleep(10); //wait for 10 milliseconds
t.interrupt(); // 'interrupt' i.e stop the thread
}
}
public class Try extends Thread {
public void interrupt() {
//perform all cleanup code here
this.stop();
/*stop() is unsafe .but if we peform all cleanup code above it should be okay ???. since thread is calling stop itself?? */
}
}
In order to perform interrupt in a good manner you should poll for the "interrupted()" method inside the thread that is being interrupted.
Just be aware that calling interrupted() method resets the interruption flag (that is set when calling interrupt()).
I guess the bottom line is that you have to continuously poll inside the thread in order to perform a graceful interruption.
You should never ever call .stop() on a Thread, period. It's not enough for the thread to perform its own cleanup. Since calling .stop() immediately releases all monitors, other threads may see shared data in an inconsistent state which may result in almost impossible to track errors.
Use Thread.interrupt() method instead of Thread.stop(). In the interrupted thread you can catch the InterruptedException and do any cleanup required.
A similar questions has already been asked here, you can find a code sample there too.

thread checking problem

I do need help.
I'm wracking my brain in order to understand how threads work.
I'm wondering what's wrong with this code?
My application has two threads. One thread starts when the user press button A, the other one
starts when the B button is chosen. If one button is enabled the other one is disabled.
Now I'd like to be able to warn the user that a thread is still running whenever he/she tries to
exit the program.
the code is....actually even though nothing is running the user is unable to exit..
Thank you very much
exitAction = new
AbstractAction("Exit") {
public void actionPerformed(ActionEvent e) {
Thread thRunning = Thread.currentThread();
if (thRunning.isAlive()) {
JOptionPane.showMessageDialog(ProgAu.this,
"Be careful.Press STOP before
exiting",
"Process running", JOptionPane.WARNING_MESSAGE);
}
else {
System.exit(0);}
}
};
--
This is one of the thread I'm refering to....
What should I do in order to detect its behaviour?
class RecThread extends Thread {
public void run() {
recFile = new File("rec.wav");
AudioFileFormat.Type fileType = null;
fileType = AudioFileFormat.Type.WAVE;
try {
targetDataLine.open(audioFormat);
targetDataLine.start();
AudioSystem.write(new AudioInputStream(targetDataLine),
fileType, recFile);
} catch (Exception e) {
showException(e);
}
playAction.setEnabled(true);
stopPlayAction.setEnabled(false);
recAction.setEnabled(true);
stopRecAction.setEnabled(false);
}
}
What's wrong with the code is that it will always warn the user. Look at this:
Thread thRunning = Thread.currentThread();
That means you're looking at the currently running thread. The one that's executing that method call, and continuing to execute actionPerformed. How could that possibly not be running? It's like someone asking out loud whether the person who is speaking is dead.
When you start off your other thread (wherever that is) you need to keep a reference to that thread... that's the one you need to test for liveness. Or alternatively (and preferably IMO) the background threads could keep increment some counter when they start, and then decrement it when they end - you can only exit if the counter is 0. That way, if your design changes to allow multiple simultaneous background threads, you don't need to change your exit-checking code. Don't forget to perform the increment/decrement in a thread-safe way (e.g. using AtomicInteger) and make sure the decrement is within a finally block, so that the counter will still be decremented even if the thread throws an exception which isn't caught.
Will Thread.currentThread() not be referring to your GUI thread? Therefore it will always be alive.
The current thread is always alive. If it were dead it would be running the code to check if it was alive. Perhaps you intended to save the other thread in a field and check if it was alive?
Thread.CurrentThread().IsAlive() ALWAYS returns true, because you're interrogating the state of the thread on which you're running the code doing the checking. You'll need to keep a handle to the worker threads when you create them, and interrogate THEIR state in this method.
This checks, if the current thread (the one that executes the lines) is alive.
You could as well ask yourself: "Am I alive?" and the answer is clear (if you are not a zombie).

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.
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;
}
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?
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
}
}
Isn't this a little like asking "How can I abort a thread when no method other than Thread.stop() is available?"
Obviously, the only valid answer is Thread.stop(). Its ugly, could break things in some circumstances, can lead to memory/resource leaks, and is frowned upon by TLEJD (The League of Extraordinary Java Developers), however it can still be useful in a few cases like this. There really isn't any other method if the third party code doesn't have some close method available to it.
OTOH, sometimes there are backdoor close methods. Ie, closing an underlying stream that its working with, or some other resource that it needs to do its job. This is seldom better than just calling Thread.stop() and letting it experience a ThreadDeathException, however.
The accepted answer to this question allows you to submit batch work into a background thread. This might be a better pattern for that:
public abstract class dispatcher<T> extends Thread {
protected abstract void processItem(T work);
private List<T> workItems = new ArrayList<T>();
private boolean stopping = false;
public void submit(T work) {
synchronized(workItems) {
workItems.add(work);
workItems.notify();
}
}
public void exit() {
stopping = true;
synchronized(workItems) {
workItems.notifyAll();
}
this.join();
}
public void run() {
while(!stopping) {
T work;
synchronized(workItems) {
if (workItems.empty()) {
workItems.wait();
continue;
}
work = workItems.remove(0);
}
this.processItem(work);
}
}
}
To use this class, extend it, providing a type for T and an implementation of processItem(). Then just construct one and call start() on it.
You might consider adding an abortPending method:
public void abortPending() {
synchronized(workItems) {
workItems.clear();
}
}
for those cases where the user has skipped ahead of the rendering engine and you want to throw away the work that has been scheduled so far.
A thread will exit once it's run() method is complete, so you need some check which will make it finish the method.
You can interrupt the thread, and then have some check which would periodically check isInterrupted() and return out of the run() method.
You could also use a boolean which gets periodically checked within the thread, and makes it return if so, or put the thread inside a loop if it's doing some repetative task and it will then exit the run() method when you set the boolean. For example,
static boolean shouldExit = false;
Thread t = new Thread(new Runnable() {
public void run() {
while (!shouldExit) {
// do stuff
}
}
}).start();
Unfortunately killing a thread is inherently unsafe due to the possibilities of using resources that can be synchronized by locks and if the thread you kill currently has a lock could result in the program going into deadlock (constant attempt to grab a resource that cannot be obtained). You will have to manually check if it needs to be killed from the thread that you want to stop. Volatile will ensure checking the variable's true value rather than something that may have been stored previously. On a side note Thread.join on the exiting thread to ensure you wait until the dying thread is actually gone before you do anything rather than checking all the time.
You appear to not have any control over the thread that is rendering the screen but you do appear to have control of the spinner component. I would disable the spinner while the thread is rendering the screen. This way the user at least has some feedback relating to their actions.
I suggest that you just prevent multiple Threads by using wait and notify so that if the user changes the value many times it will only run the Thread once. If the users changes the value 10 times it will fire off the Thread at the first change and then any changes made before the Thread is done all get "rolled up" into one notification. That won't stop a Thread but there are no good ways to do that based on your description.
The solutions that purpose the usage of a boolean field are the right direction. But the field must be volatile.
The Java Language Spec says:
"For example, in the following (broken) code fragment, assume that this.done is a non-
volatile boolean field:
while (!this.done)
Thread.sleep(1000);
The compiler is free to read the field this.done just once, and reuse the cached value in each execution of the loop. This would mean that the loop would never terminate, even if another thread changed the value of this.done."
As far as I remember "Java Concurrency in Pratice" purposes to use the interrupt() and interrupted() methods of java.lang.Thread.
The way I have implemented something like this in the past is to implement a shutdown() method in my Runnable subclass which sets an instance variable called should_shutdown to true. The run() method normally does something in a loop, and will periodically check should_shutdown and when it is true, returns, or calls do_shutdown() and then returns.
You should keep a reference to the current worker thread handy, and when the user changes a value, call shutdown() on the current thread, and wait for it to shutdown. Then you can launch a new thread.
I would not recommend using Thread.stop as it was deprecated last time I checked.
Edit:
Read your comment about how your worker thread just calls another method which takes a while to run, so the above does not apply. In this case, your only real options are to try calling interrupt() and see if has any effect. If not, consider somehow manually causing the function your worker thread is calling to break. For example, it sounds like it is doing some complex rendering, so maybe destroy the canvas and cause it to throw an exception. This is not a nice solution, but as far as I can tell, this is the only way to stop a thread in suituations like this.
Since you're dealing with code you don't have access to you're probably out of luck. The standard procedure (as outlined in the other answers) is to have a flag that is checked periodically by the running thread. If the flag is set, do cleanup and exit.
Since that option is not available to you, the only other option is to force quit the running process. This used to be possible by calling Thread.stop(), but that method has been permanently deprecated for the following reason (copied 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.
More info on this topic can be found here.
One absolute sure way you could accomplish your request (although this is not a very efficient way to do this) is to start a new java process via Runtime.exec() and then stopping that process as necessary via Process.destroy(). Sharing state between processes like this is not exactly trivial, however.
Instead of playing with thread starting and stopping, have you considered having the thread observe the properties that you're changing through your interface? You will at some point still want a stop condition for your thread, but this can be done this was as well. If you're a fan of MVC, this fits nicely into that sort of design
Sorry, after re-reading your question, neither this nor any of the other 'check variable' suggestions will solve your problem.
The correct answer is to not use a thread.
You should be using Executors, see the package: java.util.concurrent
Maybe this can help you: How can we kill a running thread in Java?
You can kill a particular thread by setting an external class variable.
Class Outer
{
public static flag=true;
Outer()
{
new Test().start();
}
class Test extends Thread
{
public void run()
{
while(Outer.flag)
{
//do your work here
}
}
}
}
if you want to stop the above thread, set flag variable to false. The other way to kill a thread is just registering it in ThreadGroup, then call destroy(). This way can also be used to kill similar threads by creating them as group or register with group.

Categories

Resources