【问题标题】:ExecutorService for Do-While Loop in JavaJava中Do-While循环的ExecutorService
【发布时间】:2016-12-19 20:24:32
【问题描述】:

我是并发新手,我正在尝试为 do-while 循环实现执行器服务并发。但我总是遇到RejectedExecutionException

这是我的示例代码:

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

但这似乎不正确。我想我在错误的地方叫停了。谁能帮我正确实现Executor Service in a do-while循环。谢谢。

【问题讨论】:

    标签: java multithreading try-catch do-while executorservice


    【解决方案1】:

    你是对的,shutdown 方法没有在正确的时间被调用。在调用shutdown 之后,ExecutorService 将不接受任务(除非您实现自己的版本)。

    您应该在已经将所有任务提交给执行程序之后调用shutdown,所以在这种情况下,在do-while 循环之后的某个位置。

    【讨论】:

      【解决方案2】:

      ExecutorService.shutdown() 阻止 ExecutorService 接受更多工作。它应该在您完成提交作业时调用。

      另外Future.get() 是一种阻塞方法,这意味着它将阻塞当前线程的执行,并且除非这个future(调用get 的地方)返回,否则循环的下一次迭代将不会继续。这将在每次迭代中发生,这使得代码非并行。

      您可以使用CountDownLatch 等待所有作业返回。

      以下是正确的代码。

      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.
      

      此外,如果您正在使用 Java 8,那么您可以查看这个答案 https://stackoverflow.com/a/36261808/5343269

      【讨论】:

      • 好点。我的 2 美分:您并不真正需要 CountDownLatch,除非您想等待所有期货完成后再处理它们中的任何一个。重要的是不要在循环内调用 Future.get;只要调用发生在循环之后,它们可能不会立即返回是可以的;这将产生与等待闩锁类似的效果。
      • @dnault 你是对的,可能是另一个执行器服务会更好,一旦结果弹出就可以用来处理结果。使用Future.get() 阻止将是不可靠的,因为列表中的第一个未来可能会使每个完成的结果都等待它。
      【解决方案3】:

      来自ThreadPoolExecutor 文档:

      被拒绝的任务

      当 Executor 已关闭时,在方法 execute(Runnable) 中提交的新任务将被拒绝,并且当 Executor 对最大线程和工作队列容量都使用有限的界限并且已饱和时。

      在任何一种情况下,execute 方法都会调用 RejectedExecutionHandler.rejectedExecution(Runnable, ThreadPoolExecutor) method of its RejectedExecutionHandler

      从您的代码中可以清楚地看出,您先调用shutdown(),然后再提交任务。

      另外,请参阅这个相关的 SE 问题以了解正确的关闭方式ExecutorService

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

      【讨论】:

        猜你喜欢
        • 2020-11-26
        • 1970-01-01
        • 2018-04-28
        • 2014-05-27
        • 2022-11-20
        • 1970-01-01
        • 1970-01-01
        • 2013-03-23
        • 1970-01-01
        相关资源
        最近更新 更多