2013-04-09 47 views
0

假設我有幾個任務可以在Java中並行運行。每個任務都會返回成功或失敗。每項任務都有相關的截止日期。如果任務在截止日期前未完成,則會中斷(所有任務均爲中斷),並返回失敗。Java中的並行任務

如果其中一個任務失敗(即返回失敗),我們會中斷所有其他正在運行的任務。

我們應該等到全部任務完成,並且如果至少一個任務返回失敗,所有任務返回成功或失敗,則最終返回任一成功。

你將如何實現它?我打算使用util.concurrent。你會建議哪些庫原語?

+0

這聽起來頗爲相似'ExecutorService.invokeAll',除了對於每個子任務,它具有所有任務的單個超時而不是獨立的超時。 – 2013-04-09 10:19:39

+0

@IanRoberts恐怕我真的需要每個任務的獨立超時。 – Michael 2013-04-09 10:26:33

回答

1

ExecutorCompletionService似乎最接近

ExecutorService ex = Executors.newCachedThreadPool(); 
    ExecutorCompletionService<Boolean> cs = new ExecutorCompletionService<Boolean>(
      ex); 
    List<Callable<Boolean>> tasks = new ArrayList<Callable<Boolean>>(); 
     ... add tasks 
    List<Future<Boolean>> futures = new ArrayList<Future<Boolean>>(); 
    for (Callable<Boolean> t : tasks) { 
     futures.add(cs.submit(t)); 
    } 
    for (!futures.isEmpty()) { 
     try { 
      Future<Boolean> f = cs.poll(1, TimeUnit.SECONDS); 
      futures.remove(f); // poll returns the same instance of Future as in the futures list 
      if (f == null || !f.get()) { // poll returns null on timeout 
       break; 
      } 
     } catch (Exception e) { 
      break; 
     } 
    } 
    // cancel remaining tasks, if all finished OK the list will be empty 
    for (Future<Boolean> future : futures) { 
     future.cancel(true); 
    } 
1

我會用ExecutorServiceCountDownLatchFuture接口的數組列表來保存任務:

List<List<String>> elements = MyPartition.partition(bigObjectList, size); 
List<Future<?>> tasks = new ArrayList<Future<?>>(); 
ExecutorService executor = Executors.newFixedThreadPool(4); 
CountDownLatch doneSignal = new CountDownLatch(10); 
for(List<String> l: elements) {   
    ReadTask worker = new ReadTask(doneSignal, l); 
    tasks.add(executor.submit(worker)); 
} 

long timeout = 10000; 
doneSignal.await(timeout, TimeUnit.MINUTES); 
boolean notFinished = false; 
if(doneSignal.getCount() > 0) { 
    for(Future<?> fut : tasks) { 
    if(!fut.isDone()) { 
     System.out.println("Sub Thread " + fut + " has not finshed!"); 
     fut.cancel(true);    
     notFinished = true; 
    } 
    } 
}