1

I am new to concurrency and I was trying to implement executor service concurrency for a do-while loop. But I always run into RejectedExecutionException

Here is my sample code:

do {    
    Future<Void> future = executor.submit(new Callable<Void>() {
    @Override        
    public Void call() throws Exception {

        // action
        return null;
    }
    });

    futures.add(future);
    executor.shutdown();

    for (Future<Void> future : futures) {
        try {
            future.get();
        }
        catch (InterruptedException e) {
            throw new IOException(e)
        }          
    } 
}
while (true);

But this seems incorrect. I think I am calling the shutdown at the wrong place. Can anyone please help me implement Executor Service in a do-while loop correctly. Thanks.

Gilad Green
  • 36,708
  • 7
  • 61
  • 95
Newbie
  • 2,664
  • 7
  • 34
  • 75

3 Answers3

3

ExecutorService.shutdown() stops the ExecutorService from accepting anymore jobs. It should be called when you're done submitting jobs.

Also Future.get() is a blocking method, which means it will block the execution of current thread and next iteration of loop will not continue unless this future (on which the get is called) returns. This will happen in every iteration, which makes the code non parallel.

You can use a CountDownLatch to wait for all the jobs to return.

Following is the correct code.

final List<Object> results = Collections.synchronizedList(new ArrayList<Object>());
final CountDownLatch latch = new CountDownLatch(10);//suppose you'll have 10 futures

do {
    Future<Void> future = executor.submit(new Callable<Void>() {
        @Override
        public Void call() throws Exception {
            // action
            latch.countDown();//decrease the latch count
            results.add(result); // some result
            return null;
        }
    });

    futures.add(future);
} while (true);

executor.shutdown();

latch.await(); //This will block till latch.countDown() has been called 10 times.

//Now results has all the outputs, do what you want with them.

Also if you're working with Java 8 then you can take a look at this answer https://stackoverflow.com/a/36261808/5343269

Community
  • 1
  • 1
11thdimension
  • 10,333
  • 4
  • 33
  • 71
  • 1
    Good points. My 2 cents: you don't really *need* a CountDownLatch unless you want to wait for all futures to complete before processing any of them. The important thing is to not call Future.get inside the loop; as long as the calls happens after the loop, it's okay that they may not return right away; this would have a similar effect as waiting for the latch. – dnault Aug 12 '16 at 19:19
  • @dnault you're right, may be another executor service would be better which can be use to process the results as soon as they pop out. Using `Future.get()` to block will be unreliable as may be the first future in the list will make every completed result wait for it. – 11thdimension Aug 12 '16 at 19:23
1

You're right, the shutdown method is not being called at the correct time. The ExecutorService will not accept tasks after shutdown is called (unless you implement your own version that does).

You should call shutdown after you've already submitted all tasks to the executor, so in this case, somewhere after the do-while loop.

pablochan
  • 5,625
  • 27
  • 42
0

From ThreadPoolExecutor documentation:

Rejected tasks

New tasks submitted in method execute(Runnable) will be rejected when the Executor has been shut down, and also when the Executor uses finite bounds for both maximum threads and work queue capacity, and is saturated.

In either case, the execute method invokes the RejectedExecutionHandler.rejectedExecution(Runnable, ThreadPoolExecutor) method of its RejectedExecutionHandler

From your code, it's clearly evident that you are calling shutdown() first and submitting the tasks later.

On a different note, refer to this related SE question for right way of shutting down ExecutorService:

ExecutorService's shutdown() doesn't wait until all threads will be finished

Community
  • 1
  • 1
Ravindra babu
  • 37,698
  • 11
  • 250
  • 211