1

I have a few tasks which are registered by

final ScheduledExecutorService ses = Executors.newScheduledThreadPool(10);
List<ScheduledFuture<?>> futures = new ArrayList<>();
        tasks.forEach(task->{
            var future = ses.scheduleWithFixedDelay(() -> run(task), 0, 3, TimeUnit.SECONDS);
            futures.add(future);
});

// and now cancel all tasks one for one after 10 seconds..
ses.scheduleWithFixedDelay(() ->
        {
            log.info("cancel task----");
            futures.get(0).cancel(false);
        }, 0, 10, TimeUnit.SECONDS);

As you can see, for each task the futures holds a task.getId() so I can obtain the ScheduledFuture of a task afterwards. I do not want to ses.shutdown() because this will shutdown the whole schedulings for the other tasks as well, which I want to avoid.

The only solution I actually see is to create one ScheduledExecutorService for each task to be able to shutdown it afterwards for a specified task, but then I cannot make use of the pooling.

How can I shutdown only a specified task within the pool?

nimo23
  • 5,170
  • 10
  • 46
  • 75
  • 1
    `scheduleWithFixedDelay` has a return value which provides you with an API which does what you want. – M. Prokhorov Feb 03 '20 at 17:48
  • I see only `getScheduledFuture().cancel(false)` but this will only cancel the task of the **actual** schedule and not the next. So the next schedule will have the task again, I dont want to cancel it over and over again..I want to remove this task completly from the queue. I dont see an appropriate API for that. – nimo23 Feb 03 '20 at 18:06
  • cancel will cancel the task and any further scheduling of it, the boolean parameter decides if you want to throw an interruption exception on the task if it is already running and blocking on a resource. – CausingUnderflowsEverywhere Feb 03 '20 at 18:16
  • @nimo23, while it's true that by default cancelled tasks won't be removed from the executor's queue immediately, the executor won't run the cancelled task any more - because `FutureTask` is a stateful object, and it won't run the actual task code in `CANCELLED` state. – M. Prokhorov Feb 04 '20 at 11:48
  • @prokhorov This is wrong. As long as the task is within the scheduled executor's queue the next task will run..does not matter if you cancel it in the actual run..for the actual run it is cancelled but not for the next run. – nimo23 Feb 04 '20 at 12:48

1 Answers1

4

Use

Future<?> future;
future.cancel(false);

Cancel will cancel the task and any further scheduling of it.¹ The Boolean parameter decides if you want to throw an interruption exception on the task if it is already running and blocking on a resource.

To ensure the task is removed from the queue immediately upon cancelling, use the setRemoveOnCancelPolicy method on your ScheduledThreadPoolExecutor and set the policy to true.²

final ScheduledThreadPoolExecutor ses = (ScheduledThreadPoolExecutor) Executors.newScheduledThreadPool(10);
ses.setRemoveOnCancelPolicy(true);

¹ https://docs.oracle.com/javase/8/docs/api/index.html?java/util/concurrent/Future.html

² https://stackoverflow.com/a/36748183/4425643 , https://docs.oracle.com/javase/8/docs/api/java/util/concurrent/ScheduledThreadPoolExecutor.html#setRemoveOnCancelPolicy-boolean-