24
votes

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();
            }
        }
    }
}
6
In Windows: Task Manager, end the javaw process. :)Buhake Sindi
@The Elite Gentleman What are you talking about? It only works for Windows users, that's not a multi-platform way to do it, and thus, it's not very Java :oPSteeveDroz
Not directly connected to your question, but don't make the mistake of calling the Runnable objects run() method, instead of the Thread objects start() method. A mistake that is quite common :S.m2o
@Oltarus, for non-windows based systems, find a java runtime process id and use kill -9 pid where pid is the java runtime process id. Happy? :PBuhake Sindi
@The Elite Gentleman Delighted!SteeveDroz

6 Answers

46
votes

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:

Deprecated. This method is inherently unsafe[...]

  • Adding your own flag and keeping an eye on it is fine (just remember to use AtomicBoolean or volatile!), but why bother if JDK already provides you a built-in flag like this? The added benefit is interrupting sleeps, making thread interruption more responsive.
5
votes

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.

4
votes

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"));
    }
}
2
votes

The only way to stop an arbitrary thread is by interrupting it. Keep a reference to it then call the interrupt method.

2
votes

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.

1
votes

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 a wait() or a join, 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.