Home > Blockchain >  Hand over ScheduledThreadPoolExecutor
Hand over ScheduledThreadPoolExecutor

Time:12-28

I have some problems understanding how exactly the ScheduledExecutorService/ScheduledThreadPoolExecutor works. I would like to have the following setup:

  1. A class which sets up the ScheduledThreadPoolExecutor, sets RemoveOnCancelPolicy to true before scheduling a task and shuts down the ScheduledThreadPoolExecutor (because I want to call the produce function in a try-catch-block). The handling of the taks shall be done in the second class, which is why I would like to hand over the ScheduledThreadPoolExecutor.
public class SetupExecutorService implements AutoCloseable {
    
    private final ScheduledThreadPoolExecutor executorService;
    private final Producer producer;

    public SetupExecutorService(Producer producer) {
        executorService = new ScheduledThreadPoolExecutor(1);
        this.producer = producer;
    }

    public void produce() {
        executorService.setRemoveOnCancelPolicy(true);
        producer.schedule(executorService);
    }
    
    @Override
    public void close() throws Exception {
        executorService.shutdown();
    }

}
  1. A second class, which actually handles the task to execute regularly:
public class Producer implements Runnable {

    public Producer(int pauseInMilliSec) {
        this.pauseInMilliSec = pauseInMilliSec;
    }

    @Override
    public void run() {
        System.out.println("calling run");
        ...
    }

    public void schedule(ScheduledExecutorService executorService) {
         executorService.scheduleAtFixedRate(this, 0, pauseInMilliSec, TimeUnit.MILLISECONDS);
    }

}

Unfortunately, this setup does not work. I am not sure where I am going wrong, however, if I simply pull the executorService inside the Producer class, everything works as expected and the task is executes regularly:

public class Producer implements Runnable {

    public Producer(int pauseInMilliSec) {
        this.pauseInMilliSec = pauseInMilliSec;
    }

    @Override
    public void run() {
        System.out.println("calling run");
        ...
    }

    public void schedule() {
         ScheduledThreadPoolExecutor executorService = new ScheduledThreadPoolExecutor(1);
         executorService.setRemoveOnCancelPolicy(true);
         executorService.scheduleAtFixedRate(this, 0, pauseInMilliSec, TimeUnit.MILLISECONDS);
    }

}

Could someone please point me towards the error?

Thanks a lot for any help :)

CodePudding user response:

When you shutdown the executor it will not accept any more tasks and only will drain up current queue of pending tasks. In case of ScheduledExecutor all future scheduled tasks are canceled and will not fire.

In other words, you are closing executor before first scheduled task is running effectively cancelling it. In your second case, you are not shutting down the executor - thus it work.

If you remove shutdown in your 'broken' setup, it will behave the same way as your 'fixed' version.

  • Related