ExecutorService, how to wait for all tasks to finish

前端 未结 15 2259
攒了一身酷
攒了一身酷 2020-11-22 15:45

What is the simplest way to to wait for all tasks of ExecutorService to finish? My task is primarily computational, so I just want to run a large number of jobs

15条回答
  •  陌清茗
    陌清茗 (楼主)
    2020-11-22 16:31

    Root cause for IllegalMonitorStateException:

    Thrown to indicate that a thread has attempted to wait on an object's monitor or to notify other threads waiting on an object's monitor without owning the specified monitor.

    From your code, you have just called wait() on ExecutorService without owning the lock.

    Below code will fix IllegalMonitorStateException

    try 
    {
        synchronized(es){
            es.wait(); // Add some condition before you call wait()
        }
    } 
    

    Follow one of below approaches to wait for completion of all tasks, which have been submitted to ExecutorService.

    1. Iterate through all Future tasks from submit on ExecutorService and check the status with blocking call get() on Future object

    2. Using invokeAll on ExecutorService

    3. Using CountDownLatch

    4. Using ForkJoinPool or newWorkStealingPool of Executors(since java 8)

    5. Shutdown the pool as recommended in oracle documentation page

      void shutdownAndAwaitTermination(ExecutorService pool) {
         pool.shutdown(); // Disable new tasks from being submitted
         try {
         // Wait a while for existing tasks to terminate
         if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
             pool.shutdownNow(); // Cancel currently executing tasks
             // Wait a while for tasks to respond to being cancelled
             if (!pool.awaitTermination(60, TimeUnit.SECONDS))
             System.err.println("Pool did not terminate");
         }
      } catch (InterruptedException ie) {
           // (Re-)Cancel if current thread also interrupted
           pool.shutdownNow();
           // Preserve interrupt status
           Thread.currentThread().interrupt();
      }
      

      If you want to gracefully wait for all tasks for completion when you are using option 5 instead of options 1 to 4, change

      if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
      

      to

      a while(condition) which checks for every 1 minute.

提交回复
热议问题