I have a class XYZ which extends Thread and it is also a singleton (Yes. My application needs that).
In the run method, I have something like this:
public void run() {
service.start();
}
The time it takes for service.start() is huge.
Also, my application will not always need the thread to be run but can't decide in advance so while launching the application I am starting this thread.
Now, when application doesn't need the thread, it gets completed very quickly and all I need to do is wait for thread to die.
I tried to use stop() method but came to know that it is deprecated.
See this article for alternatives to calling stop()
http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html
stop has been deprecated a long time ago and should not be used. Thread termination is a cooperative process in Java (i.e. the interrupted code must do something when asked to stop, not the interrupting code) - one way is to call thread.interrupt() on the thread you need to interrupt.
You then need to catch the generated interrupted exception in the running thread or check the interrupted status regularly. Once the running thread detects that is should stop what it's doing, you can then run any cleanup tasks as required and exit whatever you were doing.
Signal your thread to do it's cleanup stuff, which you said is fast anyway, then just do a Thread.join.
Your question is highly dependant on exactly what is going on in service.start(). If it's opening external resources, then naturally you can't just barge in and kill the thread without proper cleanup. The start procedure will need to be coded explicitly for interruptibility with proper cleanup.
Related
I have an application which uses a third party jar to do some task. My application uses Spring Executor pool to spawn the threads.
Question:
I need to stop the current execution of a thread if the executing time exceeds the time limit
What I did:
I googled a lot about interrupting thread. Most of says to check the interrupt flag whether the thread is interrupted or not and if interrupted throw an interrupted exception. But in thread I'm calling a method which is in a third party jar which do most of the stuffs so I can't go there and change the code for checking the interrupt flag.
Consider the following code snippet:
public void run() {
boolean isDone = false;
isDone = callThirdPartyMethod(); // here for some inputs thread takes more time (even never return for an hour!!) to process which I don't want and I need to stop/interrupt the thread
}
Approaches I follow for stopping/interrupting it
I had wrote a TimerTask which checks for the thread which is
exceeding the time limit and call the interrupt() on them (but it
seems nothing happens as they continue their execution).
I changed the code of my TimerTask from interrupting it to calling
the stop() on thread. This works but it throws ThreadDeath error.
Also what I read in most of the blogs and even in stackoverflow is
that we should never call the stop method.
Question: I need to stop the current execution of a thread if the executing time exceeds the time limit
There is no easy answer here. Typically you create one thread to make the third party library call and one thread to watch the clock and kill the other thread when a timer expires.
You can call interrupt the third party library thread but as you mention there is no guarantee that callThirdPartyMethod() will listen for the interrupt. You can call stop() but this is deprecated for good reasons.
The only addition mechanism is to close something that the third party library is using. Maybe a socket or other connection could be closes out from under the library.
If there is not way to do it then thread.stop() is your only (unfortunate) alternative unless you can get at the source of the library.
Otherwise you are SOL unfortunately.
I'm wondering why there seems to be no support for thread level 'shutdown hooks', which run when a specific thread terminates; not when the JVM terminates.
So lets say someone wrote a simple thread with a run method with sudo code like this (intentionally leaving out thread interrupt here for now...):
public void run(){
SeverSocket serverSocket=new ServerSocket(port);
while(!isStopRequested){
Socket socket=serverSocket.accept();
processRequest(socket);
}
runShutdownLogic();
}
public void stopServer(){
isStopRequested=false;
//interrupt thread potentially, see below
}
This thread could die in a few ways:
someone calls stopServer, followed by either...
a. the serversocket.accept accepting one last socket and returning
b. an interrupt sent to intterupt serverSocket.accept
an exception is thrown
Someone kills the thread, directly or through executor service.
The JVM goes down.
In any of these cases we want to run the shutdownLogic method, lets say it does something more then just close the seversocket, some interface with an external source that is important to do no matter how the thread shuts down.
As I understand it this is not very easy to do, in fact it seems hard enough that I feel I must be missing some basic threading feature. the 1a case is simple and works as is. 1b case works so long as the developer doesn't swallow interruptExceptions, something that is done way to often but is easy enough to avoid if you know what an interrupt exception is.
In case of an exception you need to move the shutdown method into a finally block.
In cases 3 & 4 though this gets harder. For 3 I think threads can be killed 'nicely', with an interrupt that one can catch, check to see it's a sigkill, and then force an exit of the code, but this requires even more intelligent handling of a InterruptException that most improperly swallow; plus would get ugly fast if this check has to be done in dozens of locations that can through interrupts. You can't do much for a hard kill, but no one expects proper shutdown logic for a hard kill so that's fine.
For a JVM shutdown...I don't actually know the exact method the threads are killed. I assume a sigkill is sent to the threads with a timeout before a hard kill, I'd have to research it more. If you want to be safe you can add a shutdown hook, but there is no gaurentee of order that shutdown hooks are run and trying to add shutdown hooks for each thread requires careful writing of the hooks to ensure you don't stall or stop the JVM shutdown with a deadlock or unexpected exception in the hook....
If instead of a thread like the one above I have a thread with a finite, but potentially long, processing time, without any waits, it gets even harder since I can't listen for an interrupted exception to know that I need to give up on my threads processing and run the shutdown logic immediately.
Basically, it seems like different method is needed to handle each manner a thread can execute, and needs to be done with every thread. And still in the case of high CPU threads without waits I still don't now how to gaurente a proper shutdown occurs if the thread (not the whole JVM) is killed midway through...
Is there not a simpler solution to all of this? For instance the equivalent of a thread level shutdown hook which will run when that specific thread is being killed, regardless of how it dies; even if JVM itself is not shutting down? Is there some reason a thread level shutdownhook is not possible or dangerous to support, assuming that such doesn't exist.
At least one of the reasons is that there really is not a safe and clean mechanism, which is also why Thread.stop() is deprecated. By creating a (seemingly) simple mechanism for it, people might think that it's a simple issue and use it wildly.
The same issue exists for finalizers and shutdownhooks. They're not reliable, so it's not a good idea to let developers think that it's a normal tool that they're supposed to use.
Yes, Java provides such a mechanism. Simply use a try/finally construction in your run() method, either in your Thread subclass or in your Runnable if you are using a Runnable:
public void run() {
try {
doBody()
}
finally {
doThreadShutdown()
}
}
This should take care of all of the cases that you are looking for, including normal shutdown of the virtual machine, since the virtual machine shuts down only after all nondaemon threads exit. Exceptions would be hard stop of the thread, hard kill of the virtual machine, or if the thread is a daemon thread and the virtual machine exits.
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. :)
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.
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.