並列ストリームは複数のブロックに分割され、各ブロックは独立して処理され、結果が末尾にまとめられています。
CPU集約型のコードは次のとおりです。
プライベート長いcountPrimes(int型の最大){ リターンの範囲(1、MAX).PARALLEL()((この:: isPrime).countをフィルタリングします)。 } プライベートブールisPrime(長いN){ 戻りN> 1 && rangeClosed(2、(長い)SQRT(N))noneMatch(除数- > N%除数== 0)。 } |
1と算出された最大値countPrimes間の素数の数。この方法によって作成された範囲のデジタルストリームは、非素数、残りの計算の総数を除外するために、パラレルモードに切り替えられます。isPrime方法は非常に効果的でないとCPUの多くを取るので、我々は、並列処理を使用し、使用可能なすべてのCPUコアを活用することができます。
別の例を見てみましょう:
プライベートリスト<StockInfo> getStockInfo(ストリーム<文字列>の記号){ リターンsymbols.parallel() .MAP(本:: getStockInfo)//低速のネットワーク運用 .collect(ToListメソッド()); } |
ティッカーシンボルのリストを入力し、我々は株式についてのいくつかの詳細を取得するために低速なネットワークオペレーションを呼び出す必要があります。ここでは、CPU集約型の業務を取り扱っておりませんが、我々はまた、並列化を使用することができます。複数のネットワークの並列実行は良いアイデアです要求します。同様に、タスク並列性の良好な流れは、同意しますか?
その場合、もう一度前の例を参照してください。大きな間違いがあります。あなたはそれを見ましたか?問題は、使用しているすべての並列ストリームことである共通のスレッドプールをフォークジョイン。あなたは長時間実行タスクを送信した場合、それが効果的にプール内のすべてのスレッドをブロックします。そのため、あなたはパラレル・ストリーム内の他のすべてのタスクをブロックします。
)要求がgetStockInfo()、別の要求コールcountPrimesを(コールする際に、サーブレット環境を想像してみてください。でも、それぞれが異なるリソースを必要とするならば、それは別のを防ぐことができます。さらに悪いことに、あなたはパラレルフロースレッドプールを指定することはできません。全体のクラスローダが同じを使用する必要があります。
のは、次の例ではそれを説明してみましょう:
プライベートボイドラン()InterruptedExceptionが{スロー ExecutorServiceのES = Executors.newCachedThreadPool(); //システムで複数のスレッドをシミュレートするそのうちの一つは、長期実行中のタスクを実行している場合//。//他のスレッド/タスクの一部が待っている、それが終了するのを// es.executeを(() - > countPrimes(MAX、1000)); //間違ったタスク es.execute(() - > countPrimes(MAX、0)); es.execute(() - > countPrimes(MAX、0)); es.execute(() - > countPrimes(MAX、0)); es.execute(() - > countPrimes(MAX、0)); es.execute(() - > countPrimes(MAX、0)); es.shutdown(); es.awaitTermination(60、TimeUnit.SECONDS)。 } プライベートボイドcountPrimes(INT MAX、INT遅延){ System.out.println(範囲(1、MAX).PARALLEL().filter(本:: isPrime).peek(I - >睡眠(遅延)))(カウントされます。); } |
ここでは、システムの6つのスレッドをシミュレートします。それは首相が第二のために眠っていた見つけた後、これらのすべては、最初は「一時停止」するようにCPU集約型のタスクによって実行されています。これは単なる不自然な例であり、あなたが立ち往生またはスレッドのブロック操作を実行していると想像することができます。
質問です:このコードが実行されたときに何が起こりますか?1が完了するまでに丸一日必要があるだろう、と残りはより迅速に完了しなければならない。我々は、6つのタスクを持っています。驚くことではないが、コードが実行されるたびに、異なる結果が得られます。あなたは、生産システムにおけるそのような行動が何がしたいですか?デュッセルドルフは、タスクは、アプリケーションの残りの部分をキャンセル?私はないと思います。
このようなことは常に、唯一の2つの選択肢が発生しないことを確実にする方法について。最初は、公共フォーク加入プールに提出されたすべてのタスクがカードでないことを保証するために、合理的な期間内に完了する必要があります。しかし、これは簡単に、特に複雑なアプリケーションでは、口で言うです。
別のオプションは、並列ストリームを使用しないことであり、オラクルのを待つ私たちは、スレッド・プールの並列ストリームを指定することができます。