2012-07-30 76 views
0

我創造,比如說,15級可贖回的任務,並提交他們:的Future.get()沒有返回所有的結果

List<Future<MyResult>> futures = new ArrayList<Future<MyResult>>(); 
List<MyResult> myResults = new ArrayList<MyResult>(); 

for(int i = 1; i <= 15; i++){ 
    Callable<MyResult> task = new MyProcessor(//parameters); 
    Future<MyResult> future = executorService.submit(task); 
    futures.add(future);//used to iterate over to call get() to collect results in next for loop 
} 

然後我收集了15 MyResult對象:

for(Future<MyResult> future : futures){ 
    try { 
    MyResult myResult = future.get(); 
    processorResults.add(myResult); 
    } catch (InterruptedException e) { 
     //... 
    } catch (ExecutionException e) { 
     //... 
    } 
} 

問題是:與get()方法返回所有15個MyResult對象相反,我有時會返回少於15個對象。有時12有時10有時甚至更小,有時全部15.

我的印象是,get()方法是一個阻塞調用,並會等待所有15個線程取回各自的結果,但看起來像我想念幾個並且繼續前進。 我做錯了什麼?我沒有收集結果/等待結果是否正確?當從任何MyProcessor任務中拋出ERROR時會發生這種情況嗎?

+1

可能傳播異常。打印ExecutionException的堆棧跟蹤 – 2012-07-30 17:41:27

+0

只是爲了記錄:get()阻塞:) – 2012-07-30 17:46:53

回答

6

這可能意味着您的某些工作引發了異常。從代碼中很難分辨出來,但除了捕捉和忽略它之外,您需要使用ExecutionException來做些什麼。

Future.get()拋出ExecutionException當您提交的Callable拋出從call()方法RuntimeException。如果方法以return正常返回,它將僅返回您的MyResult。你可以得到由做拋出的異常:

} catch (ExecutionException e) { 
    // account for the throw here, the original exception is in e.getCause() 
    // log it, count it, or ... 
    logger.error("Job threw exception: " + e.getCause()); 
} 

我的印象是,獲得下()方法是一個阻塞調用,並等待所有15個線程與各自的結果取回,

這是正確的。當您撥打future.get()時,會阻止該作業完成 - 通過拋出異常或返回。如果正在進行get()的線程中斷,則get()將拋出InterruptedException,這也應該被捕獲,而不是被忽略。

+0

因此,如果15個線程中的4個拋出異常,那麼我會失去4個MyResult對象?這意味着我只會從成功的線程獲取MyResult對象? – 2012-07-30 17:49:01

+0

Right @Kumar。如果'call(...)'方法自然返回,那麼你將得到一個'MyResult'。如果它拋出一個異常,那麼'get()'會拋出'ExecutionException'。 – Gray 2012-07-30 17:51:14

+0

事實上,我得到了一些'ClassCastException',它以某種方式找到了get()方法。看起來現在我有一個領先的關注點,可以儘快結案。謝謝格雷約翰,喬納斯。 – 2012-07-30 18:56:12