2017-09-11 57 views
-1

所以,情況是這樣的:多線程對Java數組

//Some code... 

public Map<String, String> someFunction() { 
    for (final UserDetail user : userDetailList) { 
     // the following (below) code runs in background thread 
     // long running task 
     new RecordPersonalisedDao().getPendingRecordsForUid(user.getuId(), new RecordPersonalisedDao.OnResultFetched() { 
      @Override 
      public void onResult(Result result) { 
       // callback after the user is processed 
       // put some parameter from result to map 
       map.put(user.getName(), result.getTotal()); 
      } 
     }); 
    } 
    // return map only after all users are processed 
    return map; 
} 

正如上面這段代碼的註釋中,我只希望用戶的整個列表進行處理後,要返回的最終地圖。

我不能更改RecordPersonalisedDao#getPendingRecordsForUid的功能,以使其僅在主線程中運行。

如何在java中實現這一點?

編輯:這種類型的問題可以面對一般。所以,我想在java中理解相同的解決方案。

把我的問題,簡單地說,我要像

  • 運行這段代碼在後臺陣列中的所有成員的行爲,一旦它的完成,發送一個回調。

(粗略地等)

[list_of_some_data] 
    .forEach(run this function) 
    .after(after the function is run in background for all members of list - return some value) 
+0

[用於Java線程安全的地圖(https://stackoverflow.com/questions/1792023/thread-safe-map-for-java) – Scrambo

+1

使用join()方法的可能的複製等到後臺線程完成了。 –

+2

你想要的是一個ExecutorService並使用通過提交一個任務作爲回調返回的Future。 – bhspencer

回答

1

在循環之前,創建具有等於所述用戶列表長度計數的CountdownLatch。在結果處理程序內部,更新地圖後倒計時。循環await()鎖存器被倒計數,然後返回。

+0

真正的問題是如何並行地做事。我真的不明白你的「答案」如何回答這個問題。不要誤解我的意思......但我想你沒有通過給出這樣的答案來收集你的200K聲望,是嗎? – GhostCat

+0

@GhostCat這個問題非常清楚地表明'getPendingRecordsForUid()'在後臺線程中運行,更一般的問題是如何在所有後臺任務完成之前阻止 - 在無法更改任務的約束下本身。 – erickson

+0

例如,「以下代碼在後臺線程中運行」,「我無法更改RecordPersonalisedDao#getPendingRecordsForUid的功能,以便僅在主線程中運行」和「僅在處理完所有用戶後才返回映射」 – erickson

1
public Map<String, String> someFunction() { 
    CountDownLatch cdl = new CountDownLatch(userDetailsList.size()); 
    for (final UserDetail user : userDetailList) { 
     // the following (below) code runs in background thread 
     // long running task 
     new RecordPersonalisedDao().getPendingRecordsForUid(user.getuId(), new RecordPersonalisedDao.OnResultFetched() { 
      @Override 
      public void onResult(Result result) { 
       // callback after the user is processed 
       // put some parameter from result to map 
       map.put(user.getName(), result.getTotal()); 

       //We're done grabbing the results.. count down. 
       cdl.countDown(); 
      } 
     }); 
    } 

    //Block this thread until all the results are in. 
    cdl.await(); 

    return map; 
}