I submitted bunch of jobs to an executorservice in Java and I somehow want to temporarily pause all these jobs. What's the best way to do this? How can I resume? Or am I doing this completely wrong? Should I follow some other pattern for what I want to achieve (i.e. ability to pause/resume execution services)?
In the specific case of an ExecutorService , I would vote for supporting thread interruption rather than a flag. In many frameworks, the service will be terminated with shutdownNow() .
Thread. sleep() method can be used to pause the execution of current thread for specified time in milliseconds. The argument value for milliseconds can't be negative, else it throws IllegalArgumentException .
When finished using an ExecutorService , you need to shut it down explicitly. From its javadoc: "An unused ExecutorService should be shut down to allow reclamation of its resources." Calling shutdown initiates a gradual and orderly shutdown.
To answer my own question, I found an example of a PausableThreadPoolExecutor in the javadocs of ThreadPoolExecutor itself. Here is my version using Guava's Monitors:
import com.google.common.util.concurrent.Monitor; import java.util.concurrent.ScheduledThreadPoolExecutor; import java.util.concurrent.ThreadFactory;  public class PausableExecutor extends ScheduledThreadPoolExecutor {      private boolean isPaused;      private final Monitor monitor = new Monitor();     private final Monitor.Guard paused = new Monitor.Guard(monitor) {         @Override         public boolean isSatisfied() {             return isPaused;         }     };      private final Monitor.Guard notPaused = new Monitor.Guard(monitor) {         @Override         public boolean isSatisfied() {             return !isPaused;         }     };      public PausableExecutor(int corePoolSize, ThreadFactory threadFactory) {         super(corePoolSize, threadFactory);     }      protected void beforeExecute(Thread t, Runnable r) {         super.beforeExecute(t, r);         monitor.enterWhenUninterruptibly(notPaused);         try {             monitor.waitForUninterruptibly(notPaused);         } finally {             monitor.leave();         }     }      public void pause() {         monitor.enterIf(notPaused);         try {             isPaused = true;         } finally {             monitor.leave();         }     }      public void resume() {         monitor.enterIf(paused);         try {             isPaused = false;         } finally {             monitor.leave();         }     } } I made some criticisms on your accepted answer, but they weren't very constructive... So here's my solution. I would use a class like this one and then call checkIn wherever/whenever I want pause functionality. Find it on GitHub!
import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.ReentrantLock;
/**
 * Provides a mechanism to pause multiple threads.
 * If wish your thread to participate, then it must regularly check in with an instance of this object.
 * 
 * @author Corin Lawson <[email protected]>
 */
public class Continue {
    private boolean isPaused;
    private ReentrantLock pauseLock = new ReentrantLock();
    private Condition unpaused = pauseLock.newCondition();
    public void checkIn() throws InterruptedException {
        if (isPaused) {
            pauseLock.lock();
            try {
                while (isPaused)
                    unpaused.await();
            } finally {
                pauseLock.unlock();
            }
        }
    }
    public void checkInUntil(Date deadline) throws InterruptedException {
        if (isPaused) {
            pauseLock.lock();
            try {
                while (isPaused)
                    unpaused.awaitUntil(deadline);
            } finally {
                pauseLock.unlock();
            }
        }
    }
    public void checkIn(long nanosTimeout) throws InterruptedException {
        if (isPaused) {
            pauseLock.lock();
            try {
                while (isPaused)
                    unpaused.awaitNanos(nanosTimeout);
            } finally {
                pauseLock.unlock();
            }
        }
    }
    public void checkIn(long time, TimeUnit unit) throws InterruptedException {
        if (isPaused) {
            pauseLock.lock();
            try {
                while (isPaused)
                    unpaused.await(time, unit);
            } finally {
                pauseLock.unlock();
            }
        }
    }
    public void checkInUninterruptibly() {
        if (isPaused) {
            pauseLock.lock();
            try {
                while (isPaused)
                    unpaused.awaitUninterruptibly();
            } finally {
                pauseLock.unlock();
            }
        }
    }
    public boolean isPaused() {
        return isPaused;
    }
    public void pause() {
        pauseLock.lock();
        try {
            isPaused = true;
        } finally {
            pauseLock.unlock();
        }
    }
    public void resume() {
        pauseLock.lock();
        try {
            if (isPaused) {
                isPaused = false;
                unpaused.signalAll();
            }
        } finally {
            pauseLock.unlock();
        }
    }
}
For example:
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
public class PausableExecutor extends ScheduledThreadPoolExecutor {
    private Continue cont;
    public PausableExecutor(int corePoolSize, ThreadFactory threadFactory, Continue c) {
        super(corePoolSize, threadFactory);
        cont = c;
    }
    protected void beforeExecute(Thread t, Runnable r) {
        cont.checkIn();
        super.beforeExecute(t, r);
    }
}
This has the added benefit that you can pause many threads with a single call to Continue's pause.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With