This question already has answers here:
How do you kill a Thread in Java?
(17 answers)
Closed 2 years ago.
I want to create a thread to judge user codeļ¼
FutureTask<Integer> futureTask = new FutureTask(() -> run(type)); // run is a method
Thread thread = new Thread(futureTask);
thread.start();
As we all known, an infinite loop may be written in the user code, so the method run will be working all the time and the Thread thread will not stop. I want to terminate this thread after timeout duration. How can I terminate it instead of using Thread.stop because it's unsafe?
The correct way to deal with a thread that needs to be stopped is to design the thread's code so that it responds appropriately to being interrupted:
Long computations need to occasionally check the current thread's "interrupted" flag.
InterruptedException should be handled appropriately.
The thread application code's response to the interrupt should be to gracefully stop what it is doing1 and (typically) allow the thread to terminate.
(You could also use a custom flag implemented using a volatile shared variable instead of the interrupted flag. However, that doesn't deal with interrupting wait, sleep and similar operations, and is therefore a poor substitute for interrupts.)
The unsafe way is to call the deprecated Thread.stop() method. (The javadocs explain why it is unsafe, and we don't need to repeat that here.)
The (related) Thread.stop(Throwable) method was removed in Java 11; see:
Java 11 Removes stop() and destroy() Methods.
https://bugs.openjdk.java.net/browse/JDK-8204243
Unfortunately, there is nothing in between these two approaches for interrupting a thread.
If you cannot get your long running thread to cooperate, the safe alternative would be to run it in a separate process; e.g. using System.ProcessBuilder etcetera to run the java command. The (external) process could then be killed if it took too long. The downsides include:
An external process cannot access the current JVM's variables, etcetera. So you need to use a different mechanism to pass information between the parent and child processes.
Starting a new JVM is a lot more expensive than starting a new thread.
1 - For example, if the thread owns resources such as open files or sockets, it should release them. If it is performing an action for some other thread that will be waiting for the result, it should signal (in the appropriate way) that there will be no result. And so on.
Terminating thread from outside is ALWAYS unsafe and very strongly discouraged. You need to notify the thread that you want it to terminate and the thread must do it itself. That is done with method interrupt() of the class Thread. In your example it would be from the main code to call thread.interrupt() That will cause the interrupt flag to be raised in your thread. In your run method of your thread you should check for that flag (See methods interrupted() and isInterrupted() in the class Thread). Once you see that your flag is raised, break out of the loop and finish the method. That will stop your thread.
Related
This question already has answers here:
Why do InterruptedExceptions clear a thread's interrupted status?
(4 answers)
Closed 2 years ago.
In many sources I found that Thread.interrupted() method clears interrupt status of thread, but in none of them there was explanation of the reason why this method works exactly in this way.
I still feel confused a little because of lack of understanding of this reason and lack of understating of what problem designers of java tried to solve by clearing interrupt status.
I will appreciate very much if someone could explain that and show some example.
The idea behind thread interruption is that one thread may signal another to request that it interrupt is regular processing to divert its attention to some thread-specific special action. What a thread actually does in response depends entirely on the code running in that thread.
There are two main ways in which a Thread can determine whether it has been interrupted:
Several Thread and Object methods will throw an InterruptedException if invoked in a thread whose interrupted status is set, or if a thread is interrupted while the method is executing. The interrupted status is cleared in this event, presumably because the exception is considered adequate notice of the interruption.
Code running in the thread can invoke Thread.interrupted() or Thread.currentThread().isInterrupted() to proactively test for an interrupt. The former also resets the interrupted status; the latter does not, likely because it is an instance method -- interrupts must not be lost in the event that one thread calls the isInterrupted() method of a different one.
The techniques that cause the interrupt status to be reset do so in order that the thread is able to handle subsequent interruptions. The key point here is perhaps that thread interruption is not intended to necessarily cause the interrupted thread to shut down (although that is indeed one response that a thread can make). It is a more general mechanism.
From jdoc
An interrupt is an indication to a thread that it should stop what it is doing and do something else. It's up to the programmer to decide exactly how a thread responds to an interrupt, but it is very common for the thread to terminate
and
By convention, any method that exits by throwing an InterruptedException clears interrupt status when it does so. However, it's always possible that interrupt status will immediately be set again, by another thread invoking interrupt.
So Thread.interrupted clears the flag because it's always possible that interrupt status will immediately be set again, by another thread invoking interrupt.
Explanation https://docs.oracle.com/javase/tutorial/essential/concurrency/interrupt.html
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. :)
This question already has answers here:
Is it legal to call the start method twice on the same Thread?
(11 answers)
Closed 9 years ago.
I am making a program and I need one thread to stop and another to start. my problem is that if I do t1.stop() than t1.start() I get the java.lang.IllegalThreadStateException
if (t1.isAlive() == true){
t1.stop();
// above I stop the thread and call another
t2.start();
System.out.println("t1 was playing");
}else{
t2.stop();
t1.start();
// above I stop the other thread and want to start the first thread again, but when I run the program I get the exception i said above
}
When a thread is stopped, you cannot restart it.
However, you can create and start a new thread.
Also, you can suspend and resume the thread.
The java primitive to suspend and resume a thread (along with stop etc) is deprecated. See this to figure how you can achieve best what you need - http://docs.oracle.com/javase/7/docs/technotes/guides/concurrency/threadPrimitiveDeprecation.html
Check how you can do the equivalent of suspend & resume
What should I use instead of Thread.suspend and Thread.resume?
As with Thread.stop, the prudent approach is to have the "target thread" poll a variable indicating the desired state of the thread (active or suspended). When the desired state is suspended, the thread waits using Object.wait. When the thread is resumed, the target thread is notified using Object.notify.
Example code is given in the same answer to help you achieve this.
Thread#stop is deprecated and you shouldn't use it.
From the JavaDocs
stop()
Deprecated.
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?.
Threads are also non-re-entrant, or, are single use. Once the run method terminates, they can not be restarted
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.
I am trying to stop a thread. while stopping my thread i got thread interrupted exception.
What I can do if thread throw interrupted exception. should i catch it and do nothing or do i need to do anything?
You should not 'just stop' a thread. The thing I mostly do is create a public (perhaps static) variable in the Thread's class that indicates when the thread should stop. So something like a declaration of
public volatile bool shouldStop = false;
Then, at the end of every cycle of your thread, you could check if you need to quit (break from the while-loop or something).
Threads can be very annoying to handle! Calling interrupt/stop functions on just a thread itself is possible, but mostly unwanted.
There is a reason .stop() and .suspend() were deprecated and should not be used. This article is relevant:
http://download.oracle.com/javase/1.4.2/docs/guide/misc/threadPrimitiveDeprecation.html
Also I quote the Javadocs:
Deprecated. 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?.
You should find some way (whether by some shared variable or otherwise) to synchronise your threads so the thread can end itself.
It depends on your needs. You can (for example) do something like this:
public void run() {
try {
// do thread stuff
} catch(ThreadInterruptedException ex) {
// close gracefully what needed to be closed
}
}
But the stop method is deprecated. So a better solution is to put some boolean variable to indicate whether the thread should stop or not and provide a method to change it in order to stop the thread (see this question for example).