I came across a way of stopping a Java ScheduledExecutorService which runs a periodic background task, after a time limit from this forum discussion.
In my case, I need to stop the ScheduledExecutorService when a certain condition is true. For example, I want to stop printing out "beep {count}", once the count exceeds 5. I have used the previously highlighted example for this purpose.
public class BeeperControl {
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    private int count;
    public void beep() {
        final Runnable beeper = new Runnable() {
            public void run() {
                count = count + 1;
                System.out.println("beep " + count);
                if (count == 5) {
                    scheduler.shutdown();
                }
            }
        };
        final ScheduledFuture<?> beeperHandle = scheduler.scheduleAtFixedRate(
                beeper, 1, 1, SECONDS);
    }
    public static void main(String[] args) {
        BeeperControl bc = new BeeperControl();
        bc.beep();
    }
}
Here, I have checked if the count is equal to 5 and then has used scheduler.shutdown() method to shutdown the ScheduledExecutorService.
My question is whether this is a good practice for the given scenario (as the ScheduledExecutorService is shutdown by a running task) or is there a better alternative which can be used in such a scenario?
Using Mutable state (count variable) in a Multithreaded Environment is not recommended as it may result in stale value in count variable as a Read-Increment-Write (count = count + 1) is taking place. 
It is good if you use a AtomicInteger instead of a plain old int for count variable. 
public class BeeperControl {
    private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
    private final AtomicInteger count = new AtomicInteger(0);
    public void beep() {
        final Runnable beeper = new Runnable() {
            public void run() {
                count.getAndIncrement();
                System.out.println("beep " + count);
                if (count.get() == 5) {
                    scheduler.shutdown();
                }
            }
        };
        final ScheduledFuture<?> beeperHandle = scheduler.scheduleAtFixedRate(
                beeper, 1, 1, SECONDS);
    }
    public static void main(String[] args) {
        BeeperControl bc = new BeeperControl();
        bc.beep();
    }
}
Shutting down the ScheduledExecutorService by a running task is fine as in many scenarios that is what happens. 
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