簡體   English   中英

並發執行:Future vs parallelstream

[英]Concurrent Execution: Future vs parallelstream

我編寫了一個可調用的函數來輪詢遠程客戶端以獲取信息,並以List形式返回該信息。 我正在使用threadpoolexecutor,for循環,以及Future與多個遠程客戶端並行執行任務。 然后我將所有Future列表與addAll()組合在一起,並使用巨型組合列表。

我的問題是,使用parallelstream()會比使用future和for循環更有效嗎? 編碼肯定更容易! 如果我走那條路,我會不再需要threadpoolexecutor?

謝謝!

        for(SiteInfo site : active_sites) {
            TAG_SCANNER scanr = new TAG_SCANNER(site, loggr);
            Future<List<TagInfo>> result = threadmaker.submit(scanr);

            //SOUND THE ALARMS
            try {
                alarm_tags.addAll(result.get());
            } catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        }

可能的解決方案代 Netbeans在這些方面提出了一些建議

active_sites.parallelstream().map((site) -> new TAG_SCANNER(site, loggr)).map((scanr) -> threadmaker.submit(scanr)).forEach((result) -> {
            //SOUND THE ALARMS
            try {
                alarm_tags.addAll(result.get());
            }
            catch (InterruptedException | ExecutionException e) {
                e.printStackTrace();
            }
        });

這里有幾個誤解。 首先,如果在提交任務后立即調用Future.get ,則使用異步任務不會提高資源利用率,在提交下一個任務之前立即等待其完成。

其次,Netbeans進行的代碼轉換產生了一個大致相同的代碼,仍然向Executor提交任務,所以它不是“Future vs parallelstream”的問題,因為你只是使用並行流執行提交(和等待)並仍然使用遺囑執行人。 由於你的第一個錯誤,並行執行可能會提高吞吐量,但除此之外,將兩個錯誤結合起來讓它們自行取消並不是一個好主意,它仍然是一個糟糕的解決方案:

Stream API的標准實現針對CPU綁定任務進行了優化,創建了許多與CPU核心數匹配的線程,並且當這些線程在等待操作中被阻塞時不生成新線程。 因此,使用並行流執行I / O操作,或者通常可以等待的操作,不是一個好的選擇。 而且您無法控制實現使用的線程。

更好的選擇是使用ExecutorService ,您可以根據預期的遠程客戶端I / O帶寬進行配置。 但是你應該在提交后立即修復等待的錯誤,首先提交所有任務,然后等待所有任務完成。 請注意,您可以使用流API,而不是為了更好的並行性,但可能會提高可讀性:

// first, submit all tasks, assuming "threadmaker" is an ExecutorService
List<Future<List<TagInfo>>> futures=threadmaker.invokeAll(
    active_sites.stream()
        .map(site -> new TAG_SCANNER(site, loggr))
        .collect(Collectors.toList())
);
// now fetch all results
for(Future<List<TagInfo>> result: futures) {
    //SOUND THE ALARMS
    try {
        alarm_tags.addAll(result.get());
    } catch (InterruptedException | ExecutionException e) {
        // not a recommended way of handling
        // but I keep your code here for simplicity
        e.printStackTrace();
    }
}

請注意,此處使用的流API是順序的 ,僅用於將SiteInfo列表轉換為Callable<List<TagInfo>> ,但您可以使用循環執行相同操作。

一般來說parallelstream已經寫的非常聰明的程序員非常有效地做並行處理。

有了它,就像所有其他java線程一樣,例如並發包,那么除非你是這個主題的專家,否則如果你自己編寫它你可能會:

  • 跑得慢一點
  • 介紹錯誤
  • 有更復雜/更難遵循/ etc代碼

換句話說: 是的,使用parallelstream

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM