Search code examples
javamultithreadingconcurrencyjava.util.concurrent

How to pause/restart SingleThreadExecutor (ExecutorService) in Java?


I have implemented a Singleton class "SingleTaskExecutor" which is using SingleThreadExecutor to execute one task at a time in order. This class is used to perform asynchronous database operation one at time and in order. Everything is working fine. However now we have a use case wherein we need to pause this service for a while, execute some operation, and then resume the service. Not sure how to pause/resume the service. Here is my code:

public class SingleTaskExecutor {

    private SingleTaskExecutor() {}
    private final ExecutorService executor =   Executors.newSingleThreadExecutor();

    private static class LazyHolder {
        private static final SingleTaskExecutor instance = new SingleTaskExecutor(); 
    }

    public static SingleTaskExecutor getInstance() {
        return LazyHolder.instance;
    }

    public <T> Task<T> create(Callable<T> callable) {
        Task<T> task = new Task<T>() {
            @Override
            protected T call() throws Exception {
                return callable.call();
            }
        };
        return task;
    }

    public <T> T execute(Task<T> task) {
        return (T) executor.submit(task);
    }

    public void shutDown() {
        executor.shutdown();
    }

    public void awaitTermination() {
        try {
            executor.awaitTermination(5, TimeUnit.SECONDS);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public void waitPlease() {
        try {
            Thread.currentThread().wait();
            //executor.wait();
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }

    public void resume() {
        Thread.currentThread().notifyAll();
        //executor.notifyAll();
    }
}

Solution

  • If I understood you correctly, you want to pause executions of tasks, then perform some explicit tasks, and then resume it. I actually see the following solution:

    private volatile boolean paused;
    
    public <T> T execute(Task<T> task) {
        if(paused) {
            synchronized(this) {
                if(paused) {
                    wait();
                }
            }
        }
        return (T) executor.submit(task);
    }
    
    public synchronized void waitPlease() {
        paused = true;
    }
    
    public synchronized void resume() {
        paused = false;
        notify();
    }