2017-09-11 58 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; 
}