Unable to Cleanly Stop my Thread - java

I have created a class which extends Thread.
This class has several methods defined, some of which use Process and IO streams to download files (sometimes taking several minutes).
I also have a JButton which I use to stop the thread, it has an ActionListener which currently performs a ClassName.this.stop(); and this works perfectly.
Within the 'public void run()' method, I execute some of these methods and start the thread.
My question is, how can I replace my deprecated Thread.stop() method with an interrupt(), and use it to cleanly stop the thread?
I have looked at some solutions, which recommend using a boolean flag to check whether the thread has been interrupted, but seeing that the run() method simply executes a series of methods, the loop does not evaluate until all the methods have finished executing, and even then, I get a 'InterrupedException' and then the loop starts again.
Another issue is that if a download is in progress, it could take minutes for the download to complete and for the next check to see if the Thread has been interrupted. I'd like everything to stop and for the object to 'delete itself and everything in it', which is what Thread.stop() is currently doing correctly.
Any ideas anyone?

Don't use extra boolean sentinel flags, rely fully on the interruption mechanism. In long-runnig tasks which don't spend time in interruptible blocking methods; you must handcode occasional checks of Thread.interrupted() and break out of the task if true. If your loop goes on after InterruptedException, then fix this behavior. This aspect is completely in your hands. Don't ignore the exception; react by curtailing the work and ending the method.

Related

How to stop the execution of the method in the thread in Java?

I have J2EE project which uses framework struts2 and Tomcat. There are two actions: "start task" and "stop task". As I understand it, when a user runs the task "start task", then Tomcat starts a thread where the task is executed. The user can click "stop task" and then Tomcat starts the second thread where it needs to stop the first thread. Method of action where execute task very big. There are queries to DB and calculations. In order to stop thread I use interrupt() of first thread but interrupt() just change value of flag but the code in the method continues to run. I check interrupt flag (Thread.currentThread().isInterrupted()) in different parts of method and if thread is interrupted then I use "return". Is there any other way?
Your implementation is correct. The way you are using is recommended. Other way is to use Thread.stop() but this method is deprecated since java 1.1 and no-one should use it. This method is like kill -9 in Unix, i.e. it just kills the thread that may cause program to enter inconsistent state and can produce resource leak.
Obviously you can improve your design. You said that the method is very big. Generally method should not exceed 20 lines. Well, 50 is the maximum. If your method is so big, break it into smaller tasks and check isInterrupted() before each task.
Going forward to the OO world: create interface Task with method perform(). (Names do not matter. You can choose other names).
Each subtask should be implemented in separate class and should implement this interface. Then Create special InterruptionChecker that implements Task and holds other task. It checks whether thread is interrupted and if not, runs payload task. This pattern is called wrapper or decorator.
Now your "big" method should just run all tasks in loop. When thread is iterrupted the no new tasks is performed.

Stopping a recursive function in JAVA (from within a thread)

I think that this question has been brought up a few times in the past, but this is a little different and i could not find an appropriate answer anywhere.
I have a thread which calls (inside run()) another recursive function. This is actually a game engine and the recursive function is MiniMax.
The problem is, that when the user wants to Resign a game in the middle of the calculation, or even Undo a move, then how should I stop this function?
I cannot interrupt the thread with a boolean, since if the call to Minimax has already been made, then the program is inside this function and the thread will not check the interruption condition in order to termintate, calling interrupt() also does not work.
How do I stop such a function?
Calling Thread.interrupt() will throw InterruptedException at any wait() or sleep() that you call from the thread proccess, also remember to check isInterrupted() to "not do things".
When InterrupedException is thrown from sleep/wait (or join) the interrupted status is cleared, and a call for isInterruped() will return false, so remember to interrupt() the Thread after the Exception.
Also, using boolean interrupted() instead of isInterrupted() does clear interruped status, and a double check with interrupted may result in true following by false if not interrupted again between calls.
PS: One more suggestion, if interrupt is not enough, you can has a Queue that you can send messages and consume it from the running thread and interpret the value to stop the proccess (note that it's not a static flag, it's a Queue or something similar).
This solution is actually getting aroung the problem, not too elegant, but quite creative. I found it in the source code of junit's FailOnTimeout statement. What they do is to wrap a Callable in a FutureTask then launch it using a thread. Then they call FutureTask.get(long timeout, TimeUnit unit) which returns the result or throws a TimeoutException if timeout units passed and lets the thread run as long as it wants. I think the same idea could be used here as well.

Killing Thread without periodically checking alive status

I am runnning ExecutorService to perform a heavy computation, however I don't want to pollute the algorithmic class/method code with runner operations, in this case I'd like to do periodical check if it should be terminated gracefully.
I tried to search for solutions, still with no success, what I concluded is that this is not possible because only the thread itself is allowed to "autokill himself".
So my question is, if there is any way to terminate the thread "outside" of the thread by invoking some forcefull atempt to kill the thread.
If not maybe the best solution is to use aspect and intercept each iteration by adding a kill status check ?
You can call thread.interrupt(). This can cause thread to exit if it "respects" interruptions. For example if thread is blocked on IO or on wait() or on sleep() InterruptedExcption will be thrown. However if it is "blocked" on busy loop that does not check isInterrupted() flag interruption will not work.
Other way to indeed kill the thread is to call deprecated method stop(). However this is the last possibility. This method is deprecated because it indeed kills threads immediately (like kill -9) that can cause resource leaks.
Bottom line: to be able to stop threads grecefully you have to write code that is ready for this and the standard solution is to respect thread interrupts.
There sure is a way to forcefully terminate a thread: Thread#stop, but it is almost never advisable. Your idea with aspects seems quite fruitful, but if you have any sort of a main loop in your task, then consider replacing the loop with a series of submitted tasks where each task is one iteration. This will allow ExecutorService#shutdown to interrupt the processing. All state can be carried along in the instance of Runnable that is being submitted.
I haven't used the ExecutorService much. But reading the JavaDocs it appears that you submit a callable or runnable to the service. Those methods return a Future object which have a cancel method on it.
cancel(boolean mayInterruptIfRunning)
Have you tried using that?
The method thread.interrupt() stop the thread and you can call it outside the thread itself!
If you do not want to change the original implementation, you could wrap the thread. I'm not very familar with Java, so I'm sorry for the obviously not compiling example:
class ThreadWrapper extends Thread {
public ThreadWrapper(Thread t, TerminateCallback c) {
// ...
}
#Override
public void run() {
t.start(Thread.SYNCHRONOUS);
c.done(this);
}
}
You'd need to implement TerminateCallback yourself. I also assume there is a way to start a thread synchronously, Thread.SYNCHRONOUS is just a place holder. If this condition is fulfilled, I'm sure you can transfer it into valid code. :)

Killing a thread in java android

I have an application where i need to call 3 methods in 3 seperate threads and kill them afterwards. According to the Javadoc i noticed that thread stop() and even destroy() has been deprecated. its like I start one thread after the other and then kill similarly one after the other. Is there a particular way to kill the threads because I cant use the deprecated methods
Any help much appreciated.
Thanks again
You don't kill threads. You call Thread.interrupt(), and then react to the interrupted status or InterruptedException within the thread that's being interrupted. Or, you use a volatile flag. See the official documentation for background and more info.
Even better, use a thread pool / executor instead of raw threads, as suggested in comments.
Terminating a rogue thread in a way that works every time everywhere is pretty much impossible.
If you can control the source code of the running threads, you must add a method with which you can stop the thread when you need to. Basically this method changes a boolean variable and the thread checks that value periodically to see whether or not it can continue.
public class MyTask implements Runnable {
// Set this to true when thread must stop.
private boolean mStopRequested = false;
public void run() {
while (mStopRequested == false) {
// ...
}
}
}
If you call a 3rd party libraries that do not provide such a method, then you are out of luck and have to resort to ugly kludges. Once I had to kill a long running 3rd party library call by deleting a file that was accessed by the library (it threw a FileNotFoundException and exited). And that only worked on Unix systems.
Your mileage will vary.
Use join method until the receiver finishes its execution and dies or the specified timeout expires, whatever happens first.
thread1.join(1);
thread2.join(2);
thread3.join(3);
You must handle the exception.

Stopping and Restarting a Thread

I am trying to stop a current thread, change the run() method, and then restart that thread. I've looked around, and most of the methods are deprecated. However, interrupt() is not. I'm not sure if that's all you need to do.
interrupt();
start();
Would that work for what I needed it to do? It says that you should never start a thread more than once, and I don't know if it means
start();
start();
Rather than what I wanted to do.
Any help is appreciated.
Thanks
No, you can't do that. Fron the java online docs:
It is never legal to start a thread more than once. In particular, a thread may not be restarted once it has completed execution.
Don't restart a thread. You ALWAYS can rewrite your buisness logic to do this some other way. Consider using SingleThreadExecutor
In this case, you should create a Runnable object and pass it to a thread. Then you're creating different threads, but re-using the 'work' object.
Once you've started a thread, you can only interrupt it. Once you've done that, you can't start it again. See here for more details.
I'm not quite sure what you want to do, but it sounds like you have different Runnables that you want to run in sequence. In this case use a SingleThreadExecutor and submit your Runnables. It will run these in order, and so interrupting the first (successfully) will invoke the second.
I'm still not sure this is a good idea (it just doesn't sound right) and perhaps posting a more detailed problem description will give people a better idea of what you're really trying to do.
You should look into the basics of threading more. A thread can only run once. If you want to have the thread run different code, you need to create a new thread.
The interrupt() method will not stop a thread immediately (there is no supported) way to do that, it will stop only at certain points by throwing an InterruptedException().
I think you're approaching your problem in the wrong way. You cannot 'change the run() method of a Thread'. However what you probably want is to stop the previous thread and create a new one with a different run() method.
One thing to keep in mind however, is that Threads are designed to be as autonomous as possible and they don't like interference from other threads, which is why suspend() and resume() are deprecated. They create all sorts of bad behaviour depending on the circumstances and also prone to deadlocks.
You have 2 perfectly safe alternatives however:
Use wait() and notify() on a specific shared object.
Use sleep() and interrupt()
You need to decide within the run() method where it is safe to 'stop' the thread, and at that point put a wait() or sleep(). Your thread will only stop at that point.
The other thread can then do a notify() or sleep() so that the running thread is notified or interrupted. In case of interrupt() you will get an InterruptedException which you can use to terminate what you were doing in that thread.
After interrupting the old thread you can start a new thread initialised with a new Runnable implementation which has the different run() method.
Calling interrupt() will set the thread's interrupt status potentially interrupting blocking methods. This is part of a cooperative cancellation mechanism. You can't use it to force the thread to stop running.
Stopping threads has been deprecated for a reason: it is inherently dangerous as it may leave the state variables which it is manipulating in an inconsistent state.
You should not do this. Make your code from the run() method into a Runnable and submit it for execution to an Executor. This will return you a Future which you can use to retrieve its results as well as to cancel it.
If you want to reuse the same thread for other computations, use a thread pool, see for example Executors.newFixedThreadPool() and other factory methods in Executors.

Categories

Resources