How to stop a thread that is running forever without any use
In the below code, i have a while(true) loop. considering a situation where there is some code in the try block where the thread is supposed to perform some tasks which takes about a minute, but due to some expected problem, it is running for ever. can we stop that thread ?
public class thread1 implements Runnable {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
thread1 t1 =开发者_运维知识库 new thread1();
t1.run();
}
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
try{
Thread.sleep(10);
}
catch(Exception e){
e.printStackTrace();
}
}
}
}
First of all, you are not starting any thread here! You should create a new thread and pass your confusingly named thread1
Runnable
to it:
thread1 t1 = new thread1();
final Thread thread = new Thread(t1);
thread.start();
Now, when you really have a thread, there is a built in feature to interrupt running threads, called... interrupt()
:
thread.interrupt();
However, setting this flag alone does nothing, you have to handle this in your running thread:
while(!Thread.currentThread().isInterrupted()){
try{
Thread.sleep(10);
}
catch(InterruptedException e){
Thread.currentThread().interrupt();
break; //optional, since the while loop conditional should detect the interrupted state
}
catch(Exception e){
e.printStackTrace();
}
Two things to note: while
loop will now end when thread isInterrupted()
. But if the thread is interrupted during sleep, JVM is so kind it will inform you about by throwing InterruptedException
out of sleep()
. Catch it and break your loop. That's it!
As for other suggestions:
- About Thread.stop():
Deprecated. This method is inherently unsafe[...]
- Adding your own flag and keeping an eye on it is fine (just remember to use
AtomicBoolean
orvolatile
!), but why bother if JDK already provides you a built-in flag like this? The added benefit is interruptingsleep
s, making thread interruption more responsive.
The proper way to stop a thread is to interrupt
it (stop()
is deprecated and may have nasty side effects):
t1.interrupt()
This will cause an InterruptedException
to be thrown by methods like Thread.sleep()
or Object.wait()
.
Then just add a catch block for this exception and simply break
out of the while
loop.
EDIT: I now realised that your infinite loop is running within the main thread, there's no thread created by your code, it's just run()
ning a Runnable
. You need to call Thread.start()
at some point to spawn a new thread.
Move the catch interrupt to outside the loop. This doesn't require any more lines of code, it just handles interrupts correctly i.e. the action is interrupted.
public void run() {
try{
while(true) {
Thread.sleep(10);
}
} catch(InterruptedException e){
System.out.println("Thread interrupted"));
}
}
The only way to stop an arbitrary thread is by interrupting it. Keep a reference to it then call the interrupt method.
Create a field boolean keepGoing
that you set to true
before starting your thread and replace while (true)
with while (keepGoing)
. At some point, you decide where, simply change the value of keepGoing
to false
and it will exit the loop.
I recommend using Thread.interrupt()
(as mentioned by @Bohemian). It has a couple of advantages over using ad-hoc flags:
You don't need to create and use an application-specific API to do this. (And interrupts are guaranteed thread-safe ...)
Thread.interrupt()
will interrupt threads that are blocked in await()
or ajoin
, or possibly1 some blocking I/O calls.
However, it is not a magic bullet. If the thread you are trying to stop is executing regular code, it needs to periodically check its interrupted()
flag, or it won't no to stop. This leaves us in the same as boat as we are in with an ad-hoc flag mechanism. The thread has to cooperate, or it can't be (safely) stopped.
1 - This is a murky area. On the one hand, there is an InterruptedIOException
whose javadoc says "Signals that an I/O operation has been interrupted". On the other hand, the exception is not explicitly mentioned in the javadocs for the various java.io
stream classes.
It is true that some 3rd-party code may not deal with the interrupted
flag properly, and interrupts may get "eaten" as a result. But you can check for that if you have source code. And the situation is not a lot different to the 3rd-party code not paying attention to your ad-hoc flag mechanism.
I would NOT recommend using Thread.stop()
. It is fundamentally flakey. Some people claim that it works for them, but IMO they are either dealing with a special case that works ... or they are being lucky.
精彩评论