2012-08-08 43 views
1

我正在使用此代碼來劃分不同CPU內核之間的幾百個任務。如何正確地多線程獨立任務的集合?

final List<Throwable> errors = Collections.synchronizedList(Lists.<Throwable>newArrayList()); 

    final ExecutorService pool = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors()); 

    for (...) { 

     pool.execute(new Runnable() { @Override public void run() { 

      try { 

       // TASK HERE 

      } catch (Throwable e) { 
       errors.add(e); 
      } 

     }}); 

    } 

    pool.shutdown(); 
    try { 
     pool.awaitTermination(1000, TimeUnit.DAYS); // wait "indefinitely" 
    } catch (InterruptedException e) { 
     throw new RuntimeException(e); 
    } 

    if (!errors.isEmpty()) throw Exceptions.wrap(errors.get(0)); // TODO multi-exception 

它的工作原理,但它不是很好。

  • 沒有任何版本的awaitTermination沒有超時,這是我想要的。
  • 我需要做我自己的錯誤收集。

什麼是正確/常用的方法來做到這一點?

回答

3

線程池的要點是重用線程。你應該在應用程序啓動時創建它,在創建任務的代碼之外創建它並注入它。添加任務後無需關閉池。您在應用程序關閉時執行此操作。

要運行一組任務,請使用ExecutorService.invokeAll。以後要獲得結果,請致電get返回Futures。它會重新拋出任務拋出的任何異常,所以你可以在之後收集它。

+0

我關閉池,否則'awaitTermination'將無法正常工作。 – 2012-08-08 09:39:24

+0

你也不需要做'awaitTermination'。 – artbristol 2012-08-08 09:40:04

+1

@BartvanHeukelom如果你調用future.get(),它會阻塞,直到任務完成,所以當你關閉池時,所有的東西都將被終止。 – assylias 2012-08-08 09:41:00

0

我想你需要提交每個Runnable,得到Future回來,然後在每個Future上調用get()

當您致電get()時,您將獲得Runnable的結果或遇到的異常。

1

您可以使用未來做錯誤處理:

final List<Future> futures = new ArrayList<Future>(); 
for (int i = 0; i < 5; i++) { 

    futures.add(pool.submit(new Runnable() { @Override public void run() { 
      // TASK HERE 
    }})); 

} 

for (Future f : futures) { 
    try { 
     f.get(); 
    } catch (ExecutionException e) { 
     //something bad happened in your runnable 
    } 
} 

//when you are done with the executor 

pool.shutdown(); 
try { 
    pool.awaitTermination(1000, TimeUnit.DAYS); // wait "indefinitely" 
} catch (InterruptedException e) { 
    throw new RuntimeException(e); 
}