Java 8 Streams API作为友好的ForkJoinPool外观
我最喜歡Java 8的功能之一是流API。 最終,它消除了代碼中的幾乎所有循環(huán),并使您可以編寫更具表現(xiàn)力和重點(diǎn)的代碼。
今天,我意識(shí)到它可以用于其他用途:作為ForkJoinPool一個(gè)不錯(cuò)的前端。
問題:執(zhí)行器樣板
假設(shè)我們要并行運(yùn)行許多任務(wù)。 沒什么好說的,讓我們說它們每個(gè)都只是打印出執(zhí)行線程的名稱(因此我們可以看到它并行運(yùn)行)。 我們要在完成所有操作后恢復(fù)執(zhí)行。
如果要使用ExecutorService并行運(yùn)行一堆任務(wù),則可能需要執(zhí)行以下操作:
ExecutorService executor = Executors.newCachedThreadPool(); for (int i = 0; i < 5; i++) {executor.submit(() -> System.out.println(Thread.currentThread())); } executor.shutdown(); try {executor.awaitTermination(1, TimeUnit.SECONDS); } catch (InterruptedException ex) {// TODO handle... }現(xiàn)在,這是很多代碼! 但是我們可以做得更好。
解決方案:流API
最后,我想到了這個(gè)實(shí)用程序:
void doInParallelNTimes(int times, Runnable op) {IntStream.range(0, times).parallel().forEach(i -> op.run()); }可重復(fù)使用的一切。 像這樣稱呼它:
doInParallelNTimes(5, () -> System.out.println(Thread.currentThread()));做完了
這打印出以下內(nèi)容。 請(qǐng)注意,它實(shí)際上也在使用主線程-因?yàn)樗匀槐豢蹫槿速|(zhì),并且在執(zhí)行完成之前無法恢復(fù)。
Thread[main,5,main] Thread[ForkJoinPool.commonPool-worker-1,5,main] Thread[main,5,main] Thread[ForkJoinPool.commonPool-worker-3,5,main] Thread[ForkJoinPool.commonPool-worker-2,5,main]另一個(gè)例子:并行計(jì)算
這是另一個(gè)例子。 我們可以使用流API并行處理許多不同的任務(wù),而不必重復(fù)執(zhí)行N次相同的操作。 我們可以創(chuàng)建(“種子”)具有任何集合或值集的流,對(duì)其并行執(zhí)行一個(gè)函數(shù),最后匯總結(jié)果(集合為一個(gè)集合,減少為單個(gè)值等)。
讓我們看看如何計(jì)算前45個(gè)斐波納契數(shù)的總和:
public class Tester {public static void main(String[] args) {Stopwatch stopwatch = Stopwatch.createStarted();IntStream.range(1, 45).parallel().map(Tester::fib).sum();System.out.println("Parallel took " + stopwatch.elapsed(MILLISECONDS) + " ms");stopwatch.reset();stopwatch.start();IntStream.range(1, 45).map(Tester::fib).sum();System.out.println("Sequential took " + stopwatch.elapsed(MILLISECONDS) + " ms");}private static int fib(int n) {if (n == 1 || n == 2) {return 1;} else {return fib(n - 1) + fib(n - 2);}} }打印輸出:
Parallel took 3078 ms Sequential took 7327 ms它在一行代碼中取得了很多成就。 首先,它創(chuàng)建一個(gè)流,其中包含我們要并行運(yùn)行的所有任務(wù)的描述。 然后,它并行調(diào)用所有這些函數(shù)。 最后,它返回所有這些結(jié)果的總和。
并非所有人為。 我可以輕松想象創(chuàng)建具有任意值(包括豐富的Java對(duì)象)的流,并對(duì)它們執(zhí)行非平凡的操作。 沒關(guān)系,編排所有看起來仍然相同的東西。
什么時(shí)候做?
我認(rèn)為這種解決方案在所有情況下都非常有用,當(dāng)您事先知道負(fù)載,并且您希望將執(zhí)行分叉到多個(gè)線程并在它們?nèi)客瓿珊蠡謴?fù)。 我需要一些測(cè)試代碼,但它可能在許多其他派生/合并或分而治之方案中很好地工作。
顯然,如果您想在后臺(tái)運(yùn)行某些程序并恢復(fù)執(zhí)行,或者想讓后臺(tái)執(zhí)行程序長(zhǎng)時(shí)間運(yùn)行,則無法使用。
翻譯自: https://www.javacodegeeks.com/2015/01/java-8-streams-api-as-friendly-forkjoinpool-facade.html
總結(jié)
以上是生活随笔為你收集整理的Java 8 Streams API作为友好的ForkJoinPool外观的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 问界新M7开启预售:25.8-31.8万
- 下一篇: 在三个Java IDE中生成的三种常见方