user25
user25

Reputation: 3195

Stop Thread which doesn't include while statement

All answers are about how to stop loop of some thread, but what if I don't have a loop but I still want to stop a thread before it executes/processes all lines?

For example I have a thread which usually runs for 7-10 seconds and then dies (terminates):

mThread = new Thread(new Runnable() {
   @Override
   public void run() {

    // some code here 
    // some here  
    // some here
    // some here          
    // some here
    // all lines takes about 7-10 seconds

   }
});

If I started a thread and after 2 or 3 seconds I need to stop it, then how to do it and don't wait 10 seconds?

Upvotes: 0

Views: 148

Answers (4)

Zabuzard
Zabuzard

Reputation: 25903

Explanation

The preferred way is to implement a stopping mechanism in the thread. You can also try to observe the interrupt flag. You can interrupt from outside using the Thread#interrupt method and the thread can check the flag using Thread#isInterrupted and Thread#interrupted (see documentation of Thread).

There is no way to force a thread from outside to stop without the thread actually implementing the logic by itself. There is the Thread#stop method but it is deprecated and should never be used. From its documentation:

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?.


Solution

You could modify the thread like this:

public class MyThread implements Runnable {
    private volatile boolean mShouldStop = false;

    public void shutdown() {
        mShouldStop = true;
    }

    @Override
    public void run() {
        // First line ...
        if (mShouldStop) return;
        // Second line ...
        if (mShouldStop) return;
        // Third line ...
        if (mShouldStop) return;
    }
}

So you need to periodically check the flag and then manually abort.

Usually such threads have some kind of while (true) loop. In this case it gets easier, you could do:

@Override
public void run() {
    while (!mShouldStop) {
        // Do something ...
    }
}

Depending on your application you might interpret the interruption flag as signal for a thread shutdown. Then your code could look like

@Override
public void run() {
    while (!Thread.interrupted()) {
        // Do something ...
    }
}

Note

The mShouldStop needs to be volatile to ensure it is updated correctly for the Thread. See the tutorial by Oracle for Atomic Access.

Upvotes: 3

paulturnip
paulturnip

Reputation: 106

You need to check the interrupt status in your thread. Something like this

import java.util.concurrent.TimeUnit;
import java.util.stream.IntStream;

public class ThreadInterruptor {


    private static class Worker implements Runnable {
        @Override
        public void run() {
            while (true) {
                IntStream.range(0, Short.MAX_VALUE).forEach(i ->noop());
                if (Thread.currentThread().isInterrupted()) {
                    System.out.println("i got interrupted");
                    break;
                }
            }
        }
        private void noop(){}
    }


    public static void main(String[] args) throws Exception{
        Thread thread = new Thread(new Worker());
        thread.start();
        TimeUnit.SECONDS.sleep(5);
        thread.interrupt();
    }

}

Upvotes: 0

Jose Martinez
Jose Martinez

Reputation: 12022

If your thread is not blocked, and is actually processing stuff, then interrupting it might not help. You can code the thread to check for the interrupt flag on the current thread and then stop if it sees that the flag has been set.

This is how you check to see if the current thread has been interrupted.

Thread.currentThread().isInterrupted();

So you would have to code your thread like this...

mThread = new Thread(new Runnable() {
   @Override
   public void run() {

    // some code here 
    if (Thread.currentThread().isInterrupted()) return;
    // some here  
    if (Thread.currentThread().isInterrupted()) return;
    // some here
    if (Thread.currentThread().isInterrupted()) return;
    // some here          
    if (Thread.currentThread().isInterrupted()) return;
    // some here
    // all lines takes about 7-10 seconds    
   }
});

Then you can go ahead and interrupt the mThread and it will have an effect. Though it will still continue processing the current some here step it is on.

Upvotes: 3

Pankaj Singhal
Pankaj Singhal

Reputation: 16053

You interrupt the thread with mThread.interrupt(). But, for this to work, your thread needs to check the interrupt status (by sleeping). Check out this thread.

For more details, refer this thread.

Upvotes: 0

Related Questions