I'm still battling to understand how to work with the ScheduledExecutorService. I want to have a single ScheduledExecutorService/ScheduledThreadPoolExecutor, which schedules multiple tasks and lets them run a fixed amount of times. As soon as no more tasks are scheduled, I want to shutdown the ScheduledThreadPoolExecutor. I'm trying to understand how this could work by writing some tests. The first thing I tried is the following:
@Test
public void testExecutorService() throws Exception {
ScheduledThreadPoolExecutor executorService = new ScheduledThreadPoolExecutor(1);
executorService.setRemoveOnCancelPolicy(true);
CountDownLatch latchOne = new CountDownLatch(5);
CountDownLatch latchTwo = new CountDownLatch(10);
ScheduledFuture<?> scheduledFutureOne = executorService.scheduleAtFixedRate(new MyRunnerOne(latchOne), 0, 1, TimeUnit.SECONDS);
ScheduledFuture<?> scheduledFutureTwo = executorService.scheduleAtFixedRate(new MyRunnerTwo(latchTwo), 0, 2, TimeUnit.SECONDS);
latchOne.await();
scheduledFutureOne.cancel(false);
latchTwo.await();
scheduledFutureTwo.cancel(false);
System.out.println("Shutting down service...");
executorService.shutdown();
Thread.sleep(100);
assertTrue(executorService.isTerminated());
}
class MyRunnerOne implements Runnable
{
CountDownLatch latch;
MyRunnerOne(CountDownLatch latch)
{
this.latch = latch;
}
@Override
public void run()
{
System.out.println("Do Task One : " + latch.getCount());
latch.countDown();
}
}
class MyRunnerTwo implements Runnable
{
CountDownLatch latch;
MyRunnerTwo(CountDownLatch latch)
{
this.latch = latch;
}
@Override
public void run()
{
System.out.println("Do Task Two: " + latch.getCount());
latch.countDown();
}
}
This works well and I get the expected output:
Do Task One : 5
Do Task Two: 10
Do Task One : 4
Do Task One : 3
Do Task Two: 9
Do Task One : 2
Do Task One : 1
Do Task Two: 8
Do Task Two: 7
Do Task Two: 6
Do Task Two: 5
Do Task Two: 4
Do Task Two: 3
Do Task Two: 2
Do Task Two: 1
Shutting down service...
However, I this only works because I am waiting for latchOne before waiting for latchTwo, since the first task takes less time. If I switch this order, i.e.
latchTwo.await();
scheduledFutureTwo.cancel(false);
latchOne.await();
scheduledFutureOne.cancel(false);
Task One will be executed further, even when the latch has reached zero, because it is only cancelled after Task Two. Is there a way to execute something (scheduledFutureOne.cancel(false) in this case) as soon as the latch is zero and doing so for multiple latches at once?
I also tried to follow the setup described in this answer which again works well but I do not know where/how I would shutdown the ExecutorService. The setup is similar, an atomic integer is increased until the number of desired invocations is reached and then we cancel the future. This still does not shutdown the ExecutorService though.
TLDR I would like to schedule multiple tasks with a single ExecutorService, each for a fixed number of invokations. The order in which the tasks are handled by the ExecutorService should be allowed to be random. As soon as no tasks are scheduled anymore, the ExecutorService should be shutdown.
Thank you guys for any ideas :)