次のように、計算を 8 つのスレッドに分割し、結果をファイルに書き込みます。
1a. 7 つのスレッドのそれぞれがその入力を処理し、その出力を独自の に書き込みますByteArrayOutputStream
。ストリームが閉じると、スレッドoffers
は<Integer, ByteArrayOutputStream>
aに変換され、 a (7 に初期化された) がConcurrentLinkedQueue
呼び出されます。countDown()
CountDownLatch
1b. 同時に、8 番目のスレッドが、次の反復で処理されるすべての入力データを読み取ります。このスレッドは、データの読み取りが終了awaits
したときに実行されます。CountDownLatch
2a. がCountDownLatch
0 になると、8 番目のスレッドが起動し、をソート キーとしてConcurrentinkedQueue
使用しInteger
て<Integer, ByteArrayOutputStream>
ソートし、キューを反復処理してバイト配列をファイルに追加します。(ソートせずに順番にリストをトラバースするより効率的な方法があるかもしれませんが、リストには 7 つの要素しかないため、ソート メソッドの実行時間は問題になりません。)
2b. 同時に、他の 7 つのスレッドは、8 番目のスレッドによって準備された入力を処理します。
** このプロセスは、すべてのデータが処理されるまでループします (通常、40 ~ 80 回の反復)。
各スレッドは、8 MB の同じサイズの入力チャンク (おそらく最後の反復を除く) を処理します。それぞれByteArrayOutputStream
に 1 ~ 4 MB が含まれており、出力サイズを事前に知ることはできません。通常、最も早く完了した CPU バウンド スレッドと最も遅く完了した CPU バウンド スレッドの実行時間は、互いに 20% 以内です。
すでにこのようなことをしている IO ライブラリ (または私が見逃した java.io または java.nio のメソッド) があるかどうか疑問に思っています。現在、8 番目のスレッド (IO スレッド) は約 75% アイドル状態です。しかし、この非効率性を軽減するために私が思いついた方法はどれも複雑すぎると思います (したがって、デッドロックやデータ競合を引き起こすという点でリスクが高すぎます)。たとえば、入力を 4 MB のチャンクに分割し、2 つのチャンクを 7 つの CPU バウンド スレッドに割り当て、1 つのチャンクを IO バウンド スレッドに割り当てると、理論的には IO スレッドのアイドル時間が 25% ( IO、4 mb チャンクで 50%、25% アイドル)、これは脆弱なソリューションであり、別の CPU に移植できない可能性があります (つまり、別の CPU では、ランタイムがCPU バウンド スレッドの 150%) - I'