How to Pause and Resume a Thread in Java from Another Thread

How pause and then resume a thread?

Using wait() and notify() methods:

wait() - Causes the current thread to wait until another thread invokes the
notify() method or the notifyAll() method for this object.

notify() - Wakes up a single thread that is waiting on this object's monitor.

How to Pause and Resume a Thread in Java from another Thread

You can't definitively pause one thread from another in the way you seem to want.

What you need to do instead, is signal that the other thread should stop, by setting some sort of flag. The thread in question must have logic to check this flag and pause its work when that happens.

So in this particular case, perhaps change MyThread as follows:

class MyThread extends Thread {

private volatile boolean running = true; // Run unless told to pause

...

@Override
public void run()
{
for(int i=0 ; ; i++)
{
// Only keep painting while "running" is true
// This is a crude implementation of pausing the thread
while (!running)
yield;

area.setText(i+"");
}

public void pauseThread() throws InterruptedException
{
running = false;
}

public void resumeThread()
{
running = true;
}

}

This is a crude example that for brevity uses a sort of spinlock rather than proper monitor-based sleeping. Hopefully though it communicates the idea of how you use a flag to control the pausing of the thread.

Note that if you were doing some long-running set of steps within the block, instead of just the setText call, it would be good practice to check Thread.currentThread().interrupted() between each of the steps - and exit the loop if the itnerrupt flag is set. This is broadly what the built-in blocking methods (e.g. I/O) do so that they can be interrupted by other threads - since the running flag is only checked one per loop, it doesn't do much good to set it if each loop takes 20 minutes.

Pause Thread and resume it from where it stopped

There are plenty of ways to manipulate threads.

suspend(): puts a thread in a suspended state and can be resumed using resume()

stop(): stops a thread

resume(): resumes a thread, which was suspended using suspend().

notify(): Wakes up a single thread.

wait(): makes the current thread wait.. (or sleep) until another thread invokes the notify() method for that thread.

notifyAll(): will wake up all sleeping (waiting) threads.

Note

In the latest versions of Java resume( ), suspend( ) and stop( ) has been deprecated

Question from OP

but when I wake it up, it resumes from where? Does it start from the beginning or from where it left?

Imagine a simple for-loop.

Starting thread 1.
Starting thread 2.
Thread 1: 0
Thread 2: 0
Thread 1: 1
Thread 2: 1
Pausing thread 1.
Thread 2: 2
Thread 2: 3
Thread 2: 4
Resuming thread 1.
Thread 1: 2
Thread 2: 5

How do I pause Threads properly with wait() and notify()

So given this is your Thread class:

public class MyThread extends Thread
{

First, you need an lock object. This object can be everything, and if you use an existing object this takes less memory. Also define a flag if the bot should be paused.

    public Object lock = this;
public boolean pause = false;

Now, define a pause() and continue() method for the thread. This sets the pause flag.

    public void pause ()
{
pause = true;
}

public void continue ()
{
pause = false;

Here you need to wake up the thread. Note the synchronized on the lock object so that you don't get an IllegalMonitorStateException.

        synchronized (lock)
{
lock.notifyAll();
}
}

No, define a method that automatically pauses the thread when it should be paused. You might call this at every moment when the thread can be paused.

    private void pauseThread ()
{
synchronized (lock)
{
if (pause)
lock.wait(); // Note that this can cause an InterruptedException
}
}

Now, you can define your thread in the run() method:

    public void run ()
{
task1();
task2();

pauseThread();

task3();
task4();
task5();
task6();
task7();

pauseThread();

task8();
task9();
task10();
}
}

Pause/Resume a Thread

You need to change your download() method to check for a stop or pause event and then stop or pause the thread. It has to be this way as the JVM does not know what steps need to be done in order to safely pause/stop the thread.

You may end up using wait but not the way you are using it. wait causes the currently running thread to wait until some calls notify on the object you have called wait on.

In the download method you have a loop (read a block, write a block). You should add two checks in the loop.

while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
if(paused) {
// How do you want to handle pausing? See below for options.
}
if(stopped) {
// delete the file and close the streams.
}
}

How you handle pausing is up to you. I can see two options: Save what you have as ".incomplete" and later restart the download using the Range header or continue looping with a pause (Thread.sleep, Object.wait or whatever).
I would go with the first option (Range Header). It is more work but also more robust.

how to pause a thread and resume it exactly where it was left off

There are two very useful classes in concurrency package - CountDownLatch and CyclicBarrier. If you need this behaviour only once, you probably want the first one (as it cannot be reset).

Thread 1 will await until notified by thread 2. Once it was counted down to 0, thread 1 will never block again at await():

CountDownLatch cdl = new CountDownLatch(1);

// thread 1:
cdl.await();

// thread 2:
cdl.countDown();

Threads will block at await() until there are exactly two threads waiting:

CyclicBarrier barrier = new CyclicBarrier(2);

// both threads:
barrier.await();

EDIT:

Here is what I came up with when modifying your code, however it is unclear to me whether it is expected behaviour.

Note a volatile keyword on the CountDownLatch - it is very important here, otherwise taskThread may cache the initial object (new CountDownLatch(0)) and hence never block.

public class Test {

private Thread taskThread;
private Thread busyThread;

private volatile CountDownLatch cdl = new CountDownLatch(0);

public static void main(String args[]) throws Exception {
Test t = new Test();
t.runTaskThread();
t.runBusyThread();
}

public void runTaskThread() {
taskThread = new Thread(() -> {
for (int x = 0; x < 100; x++) {
waitIfSystemBusy();
System.out.println("I'm doing task A for process #" + x);
sleep(1000);

waitIfSystemBusy();
System.out.println("I'm doing task B for process #" + x);
sleep(200);

waitIfSystemBusy();
System.out.println("I'm doing task C for process #" + x);
sleep(300);

waitIfSystemBusy();
System.out.println("I'm doing task D for process #" + x);
sleep(800);

System.out.println("\n\n");
}
});

taskThread.start();
}

public void runBusyThread() {
busyThread = new Thread(() -> {
while (true) {
Random rand = new Random();
int randomNum = rand.nextInt(1000);
if (randomNum < 400) {
System.out.println("Wait...system is busy!!!");
cdl = new CountDownLatch(1); // signal taskThread to pause
sleep(3000);
cdl.countDown(); // signal taskThread to resume
} else {
sleep(300);
}
}
});

busyThread.start();
}

private void waitIfSystemBusy() {
try {
cdl.await();
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}

private static void sleep(int millis) {
try {
Thread.sleep(millis);
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}

}

Best Method to pause a Thread?

In the FIRST case, when i use Thread.sleep inside loop the Netbeans IDE issues warning not to use Thread.sleep inside loop. Why is that?

I guess because Netbeans thinks that it won't be testing the loop condition and the code will pause unnecessarily.

In the SECOND case, when i use infinite empty while loop, is that a performance overhead?

Uh yes. Spinning a thread will take a CPU and be a performance sink.

Which method(mentioned above or otherwise) should i prefer to pause the action being performed by the Thread according to the users choice?

Neither? I would use a volatile boolean pauseFlag for testing if the thread should pause, combined with wait/notify to unpause it. Or you can use an AtomicBoolean which wraps a volatile boolean but is also an object we can synchronize on. Maybe something like:

// using `AtomicBoolean` which wraps a `volatile boolean` but is const object
// NOTE: we _can't_ synchronized on Boolean, needs to be constant object reference
private final AtomicBoolean pauseFlag = new AtomicBoolean(false);
...
while (!Thread.currentThread().isInterrupted()) {
if (pauseFlag.get()) {
synchronized (pauseFlag) {
// we are in a while loop here to protect against spurious interrupts
while (pauseFlag.get())) {
try {
pauseFlag.wait();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
// we should probably quit if we are interrupted?
return;
}
}
}
}
...
}
...
public void pause() {
pauseFlag.set(true);
}
...
public void resume() {
pauseFlag.set(false);
synchronized (pauseFlag) {
pauseFlag.notify();
}
}

I guess if I were forced to pick from one of the two, I would pick the sleep(...) loop. Even sleep(1) is significantly better than a spin. Do you really need to un-pause quicker than ~1ms? But the wait/notify is the most efficient.

Because it has nothing to do with synchronization, i do not want to use wait/notify.

As mentioned by @Jon, some sort of synchronization is necessary here since you are trying to communicate between two threads. Certainly you need to have memory synchronization otherwise any updates to pauseFlag will not be guaranteed to be shared between threads. This is handled by the volatile primitive on pauseFlag. By using wait/notify (which needs synchronized) your code can be much more efficient about the wakeup.



Related Topics



Leave a reply



Submit