Business
Jobs
  • About Us
  • Solutions
    • Job Postings
      Post your job and receive qualified candidates in 48h.
    • Candidate Assessments
      500+ technical and psychological tests, plus anti-fraud.
    • Headhunting
      Tailor-made executive search from start to finish.
    • Payroll + EOR
      Payroll dispersal and EOR across 15+ LATAM countries.
  • Pricing
  • Jobs

0

228
Views
How to correctly shutdown ScheduledExecutorService

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 :)

over 4 years ago · Santiago Trujillo
1 answers
Answer question

0

It will be easier to do if you make the tasks reschedule themselves in the executor service:

ScheduledThreadPoolExecutor executorService = new ScheduledThreadPoolExecutor(1);
CountDownLatch latchOne = new CountDownLatch(1);
CountDownLatch latchTwo = new CountDownLatch(1);

executorService.submit(new MyRunnerOne(executorService, latchOne, 5));
executorService.submit(new MyRunnerTwo(executorService, latchTwo, 10));

latchTwo.await();
latchOne.await();

System.out.println("Shutting down service...");
executorService.shutdown();
executorService.awaitTermination(100, TimeUnit.SECONDS);
System.out.println("Terminated: " + executorService.isTerminated());

//...

class MyRunnerOne implements Runnable {
    private final ExecutorService service;
    private final CountDownLatch latch;
    private final int count;

    MyRunnerOne(ExecutorService service, CountDownLatch latch, int count) {
        this.service = service;
        this.latch = latch;
        this.count = count;
    }

    @Override
    public void run() {
        System.out.println("Do Task One : " + count);
    
        if (count > 1) {
            service.submit(new MyRunnerOne(service, latch, count - 1));
        } else {
            latch.countDown();
        }
    }
}

Full code.

over 4 years ago · Santiago Trujillo Report
Answer question
Find remote jobs

Discover the new way to find a job!

Top jobs
Top job categories
Business
Post vacancy Pricing Sales
Legal
Terms and conditions Privacy policy
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Show me some job opportunities
There's an error!