2016-08-12 58 views
1

我是新来的并发性,我试图为do-while循环实现执行程序服务并发。但是,我总是碰上RejectedExecutionException用于在Java中执行Do-While循环的ExecutorService

这里是我的示例代码:

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循环。谢谢。

回答

3

ExecutorService.shutdown()使ExecutorService停止接受任何工作。应在您提交作业完成后调用。

另外Future.get()是一个阻塞方法,这意味着它会阻止当前线程的执行,并且除非这个将来(在其上调用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

+1

好点。我的2美分:除非您希望在处理任何期货之前等待所有期货的完成,否则您并不需要* CountDownLatch。重要的是不要在循环中调用Future.get;只要呼叫在循环后发生,可以立即返回;这与等待锁存器有类似的效果。 – dnault

+0

@dnault你是对的,可能是另一个执行者服务会更好,可以用它来处理结果,一旦他们弹出。使用'Future.get()'来阻止将是不可靠的,因为列表中的第一个将来可能会使每个完成的结果等待它。 – 11thdimension

1

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

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

0

看看,ThreadPoolExecutor文档:

被拒绝任务提交

新任务方法执行(Runnable)将在执行程序关闭时被拒绝,并且执行程序对最大线程和工作队列的容量都使用有限范围时,并饱和。

在两种情况下,执行方法调用RejectedExecutionHandler.rejectedExecution(Runnable, ThreadPoolExecutor)method of its RejectedExecutionHandler

从你的代码,这是显而易见的,你在呼唤shutdown()首尔后提交任务。

在不同的音符,请参阅本有关SE问题的正确途径关停ExecutorService的:

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