I have a thread which executes code periodically, e. g. every 10 seconds. I'd like to have the option to also invoke the same code in a spontaneous way and not have to wait 10 seconds. But the code of the automatic and spontaneous execution must never run concurrently, instead they should run in sequence if the user presses the execute button while the thread is invoking the same method.
Does anyone know a good pattern or even a class that can address this kind of requirement?
First thing that comes to mind would be to make the work method synchronized. But in that case the manual execution (e. g. button press) is blocked and has to wait until the method in the thread is finished. Is there a better approach without blocking?
Example:
public class Executor extends Thread {
    // endless loop, executes work method periodically with pause inbetween
    @Override
    public void run() {
        while( true) {
            work( "automatic");
            pause(10000);
        }
    }
    // Working method that's executed periodically or manually
    private synchronized void work( String text) {
        System.out.println( "Working " + text + " " + System.currentTimeMillis());
    }
    // helper method that pauses the thread
    private static void pause( long sleepMs) {
        try {
            Thread.sleep(sleepMs);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    public static void main(String[] args) {
        // start automatic execution
        Executor executor = new Executor();
        executor.start();
        // pause a while
        pause(1000);
        // manual execution
        executor.work( "manual");
    }
}
Edit: Solution for my requirement:
public class ScheduledExecutor {
    public static void main(String[] args) throws InterruptedException {
        ScheduledThreadPoolExecutor executor = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(1);
        executor.scheduleWithFixedDelay(new Work("auto"), 0, 10, TimeUnit.SECONDS);
        Thread.sleep(1000);
        executor.execute(new Work("manual"));
    }
    public static class Work implements Runnable {
        String text;
        public Work(String text) {
            this.text = text;
        }
        @Override
        public void run() {
            System.out.println("Working " + text + " " + System.currentTimeMillis());
        }
    }
}
 
     
     
    