Java版本:11
我有物件串列,我想對它們執行某些操作,其中一個操作取決于另一個操作的結果。為了以異步方式實作此作業流程,我使用CompletableFuture.
目前,我通過將串列劃分為子串列并將每個子串列分配給 來執行此操作CompletableFuture,因此我的執行緒池中的每個執行緒都可以開始處理該子串列。
我使用和作業的上述方法的代碼是:
List<SomeObject> someObjectList // original list
List<List<SomeObject>> partitionList = ListUtils.partition(someObjectList, partionSize);
partitionList.forEach(subList -> {
CompletableFuture.supplyAsync(() -> firstOperation(subList), executorService)
.thenAcceptAsync(firstOpresult -> secondOperationWithFirstOpResult(firstOpresult),executorService);
});
public static List<String> firstOperation(List<SomeObject> subList){
//perform operation
return List<String>;
}
public static void secondOperationWithFirstOpResult(List<String> firstOpProducedList) {
//perform operation
//print results.
}
這里的問題是對原始串列進行磁區,
因為如果我的原始串列有 10 萬條記錄并且磁區大小是 100(這意味著我希望每個子串列中有 100 個專案),我將有 1000 個子串列物件,每個物件包含 100 個元素,考慮到記憶體中有這么多物件,這可能不是很好,此外,如果磁區大小是用戶控制/配置控制器,則較小的磁區大小將導致大量子串列物件。
而不是對原始串列進行磁區,
- 我想拿原始串列。(比如 100 個元素)
- 在原始串列上有一個 startIndex 和 endIndex(比如 0 到 9、10 到 19...)
- 并將這些批次中的每一個都交給一個執行緒,在執行緒池中使用 CompletableFuture
- 所以這個執行緒可以執行這兩個操作。
我知道 SO 不是精確解決方案的地方,但如果你能把我推向正確的方向,一個偽代碼,或者即使這CompletableFuture首先是可能的,也會有很大的幫助:)
uj5u.com熱心網友回復:
由于ListUtils.partition不是標準方法,因此無法說它是如何作業的。但如果它以“聰明的方式”作業,它將subList在原始串列上使用,而不是復制資料。
如果您想安全起見,您可以自己進行簡單的磁區:
IntStream.range(0, (someObjectList.size() partionSize - 1) / partionSize)
.forEach(p -> {
int start = p * partionSize,
end = Math.min(someObjectList.size(), start partionSize);
List<SomeObject> subList = someObjectList.subList(start, end);
CompletableFuture.supplyAsync(() -> firstOperation(subList), executorService)
.thenAcceptAsync(r -> secondOperationWithFirstOpResult(r), executorService);
});
例如,由于這些子串列不存盤元素,因此它們比CompletableFuture實體消耗更少的記憶體。所以這沒什么好擔心的。
但是,如果您可以使用默認執行緒池1而不是executorService,則可以使用
IntStream.range(0, (someObjectList.size() partionSize - 1) / partionSize)
.parallel()
.forEach(p -> {
int start = p * partionSize,
end = Math.min(someObjectList.size(), start partionSize);
List<SomeObject> subList = someObjectList.subList(start, end);
secondOperationWithFirstOpResult(firstOperation(subList));
});
其中每個子串列僅在處理時存在。
這已經在后臺使用了 Fork/Join 任務。無需自己實作這些 Fork/Join 操作。
1 默認池未指定,但將ForkJoinPool.commonPool()在實踐中使用。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/532703.html
上一篇:KotlinAndroid中的runOnUiThread和CoroutineScope(Dispatchers.Main)有什么區別嗎
下一篇:為什么結果不同逐個回圈添加執行緒
