How should I terminate a looped sub-thread in Java? - java

I need to do some clean up work when I am going to terminate a looped thread. Such as saving a buffer so I can continue later.
PseudoCode:
private class CalculatePI(Byte[] resume) implements Runnable{
public void Run(){
while(true){
resume=resumeCalculating(resume);
}
}
}
Thread calculator= new Thread(new CalculatePI(Byte[] resume));
Thread.sleep(200);
//And now I want to kill calculator
So what's the best way implement this?
Use a flag: But the problem is what if resumeCalculating() takes (EDIT: a long time) forever to end?
Put an exception into calculator, how?
Can I use event listeners or something? I thought they were used for GUIs
Just stop it? And Class Thread includes some kind of deconstructor that will be called when the thread is terminated and I could do the processing there?
EDIT by Owner:
I know I can use a flag. But consider this:
public void Run(){
while(true){
resume=calculate_stepone(resume); //takes one minute
resume=calculate_steptwo(resume); //takes two minutes
resume=calculate_stepthree(resume); //takes three minutes
resume=calculate_steplast(resume); //takes four minutes
}
}
Is putting a if(flag) saveResultsAndExit(); between every line practical or pretty?
I just want to throw away the half-processed results, and save the previous results.

The proper way to stop a thread is to interrupt it.
If the task running in the thread is performing IO or is using sleep then it will receive the signal (InterruptedException at that point); else the task should regularly poll to see if its interrupted.
Lets adapt the original poster's psuedocode:
private class CalculatePI(Byte[] resume) implements Runnable{
public void Run(){
while(!Thread.interrupted()) { //###
resume=resumeCalculating(resume);
}
}
}
Thread calculator= new Thread(new CalculatePI(Byte[] resume));
calculator.run(); //###
//...
//And now I want to kill calculator
calculator.interrupt(); //### sends the signal
//...
calculator.join(); //### actually waits for it to finish

Answer to 1.: You can process the abort flag in resumeCalculating() too.

It is probably best to use a flag, wait for a while for the thread to end, and if it hasn't (resumeCalculating hasn't returned) kill the thread manually. It is probably best not to involve too much thread based logic in resumeCalculating, it really depends on how it is implemented as to how easy it is to abort halfway through an operation.

Design your program so that resumeCalculating does NOT take forever to continue. Also, synchronize access to your flag.

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;
}
}
}
}

Java: How to stop thread? [duplicate]

This question already has answers here:
How do you kill a Thread in Java?
(17 answers)
Closed 9 years ago.
Is there any way to stop another thread from OUTSIDE of the thread?
Like, if I ran a thread to run that thread and caused that thread to stop? Would it stop the other thread?
Is there a way to stop the thread from inside without a loop?
For example, If you are downloading ideally you would want to use a loop, and if I use a loop I wont be able to pause it until it reaches the end of the loop.
We don't stop or kill a thread rather we do Thread.currentThread().isInterrupted().
public class Task1 implements Runnable {
public void run() {
while (!Thread.currentThread().isInterrupted()) {
................
................
................
................
}
}
}
in main we will do like this:
Thread t1 = new Thread(new Task1());
t1.start();
t1.interrupt();
You can create a boolean field and check it inside run:
public class Task implements Runnable {
private volatile boolean isRunning = true;
public void run() {
while (isRunning) {
//do work
}
}
public void kill() {
isRunning = false;
}
}
To stop it just call
task.kill();
This should work.
One possible way is to do something like this:
public class MyThread extends Thread {
#Override
public void run() {
while (!this.isInterrupted()) {
//
}
}
}
And when you want to stop your thread, just call a method interrupt():
myThread.interrupt();
Of course, this won't stop thread immediately, but in the following iteration of the loop above. In the case of downloading, you need to write a non-blocking code. It means, that you will attempt to read new data from the socket only for a limited amount of time. If there are no data available, it will just continue. It may be done using this method from the class Socket:
mySocket.setSoTimeout(50);
In this case, timeout is set up to 50 ms. After this time has gone and no data was read, it throws an SocketTimeoutException. This way, you may write iterative and non-blocking thread, which may be killed using the construction above.
It's not possible to kill thread in any other way and you've to implement such a behavior yourself. In past, Thread had some method (not sure if kill() or stop()) for this, but it's deprecated now. My experience is, that some implementations of JVM doesn't even contain that method currently.
The recommended way will be to build this into the thread. So no you can't (or rather shouldn't) kill the thread from outside.
Have the thread check infrequently if it is required to stop. (Instead of blocking on a socket until there is data. Use a timeout and every once in a while check if the user indicated wanting to stop)
JavaSun recomendation is to use a shared variable as a flag which asks the background thread to stop. This variable can then be set by a different object requesting the thread to terminate.
You can that way kill the other process, and the current one afterwards.

Java: Thread/task expiration after specified milliseconds

In Java is there a sane way to have a thread/task run continuously and then end after a specified run time (preferably without using several timers)?
For instance, if I have a TimerTask, there doesn't seem to be a way to schedule that task to end after a certain number of milliseconds or at a specific time with the Timer class.
Sure, I can schedule a task to repeat after a number of milliseconds, but what if I want it to end after one iteration? I have to run another timer within this scheduled task? I'm hoping for a more elegant answer than that.
The answer provided in this question could work, but it is definitely not what I had in mind.
Essentially, I'm looking for something similar to the AutoReset property on C#'s System.Timers.Timer class
You can use an ExecutorService, grab the Future you get and .cancel() it after the time you want:
final Future<Whatever> f = executor.submit(...);
TimeUnit.SECONDS.sleep(xxx);
f.cancel(true);
Or you can have two services: one which executes, another which uses a ScheduledExecutorService for the cancellation.
NOTE: TimerTask depends on the system time, use a ScheduledExecutorService instead.
Simply create another thread and have it time it for when it wants the other thread to stop:
class ThreadTimer implements Runnable {
public void run()
{
Thread.sleep(3000);
MainThread.stopThread();
}
}
class MainThread implements Runnable {
public boolean running = true;
public void run()
{
// thread running code
if(!running)
return;
}
public static void stopThread()
{
running = false;
}
}
Where 3000 is the amount of time in milliseconds from when you want the thread to stop.
Since Thread.stop() is deprecated in Java, the next best way is to only execute the thread if a boolean is set to true. When you call to stop the thread, you're setting that boolean to false, making the code in the thread not run.
Because the void run() doesn't repeat itself and only executes once, if you set the boolean to false, it simply returns run() and halts the thread's execution.
If your task is running in a loop, you can check the current time on each iteration, and terminate the loop if enough time has passed.
Or, if your task involves sleeps, you can set a timer on another thread to call Thread.interrupt on the task.
The only other option would be to set a timer on another thread to call Thread.stop. However, Thread.stop has been deprecated, and there's no safe way to stop a general thread in Java.

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).

Java kill or terminate a thread

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.

Categories

Resources