ForkJoinPool概要
エグゼキュータのようなForkJoinPoolが、差があるが、ForkJoinPoolがあること、これらのタスクは、より小さなタスクに分割することができ、実行するために、このプロセスを小さなタスクに大きなタスクを分割するために、再帰的に実行しましたフォークと呼ばれ、最終的にこれらの小さなタスクのレイヤーを結合、加入と呼ばれるプロセス。
そしてForkJoinPoolは、ミッションのスレッドを作業が盗むと呼ばれるアルゴリズムを導入しForkJoinPoolはForkJoinTaskに保存されているダブルエンドのタスクキューワークキューを維持ForkJoinWorkerThread、です。スレッドをプレイするために自分のタスクを乾燥させるとき、彼は、タスクスレッドをしませんでした他のタスクのプレイから盗む、およびタスクを盗むために、スレッドは、ヘッドキューから、尾部にこのキューから盗まれたタスク・スレッドがかかります取ります。
私たちは常に、このホリデーシーズンの宿題をやって、小学校で使用されるべきであるというこのアイデアは、接触数人の友人が、友人が行う。1-10 A、Bの友人が11-20やる、というように、そして最終的に友人にコピーをもたらし、プレーを書くために、すぐにブック。
フォーク
複数のサブタスクに自分自身を入れて、各サブタスクがサブタスクがあまりにも多くの場合、あなたはそのような10の上に疑いの友人Aとして除算、あなたの友人のシェアを聞かせすることができますすることができ、異なるCPUまたは同じCPU上で異なるスレッドによって実行することができます5ページ、コピーを引き継ぐことが最後。
加わります
それは上向きサブタスクをマージされます。しかし、時には、タスクが値を返す必要がないため、マージする必要はありません。
例えば
示されるように、プログラム10、9.5MのTXTのそれぞれのサイズを読み、そして最終的にStringBufferに格納されているすべてのコンテンツへのTXT必要。
シングルスレッドでは、695ミリ秒かかる場合があります。
private static void testSingleThread() throws IOException {
long l = System.currentTimeMillis();
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < 10; i++) {
File file = new File("/home/cookie", i + ".txt");
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
while (true) {
String s = bufferedReader.readLine();
if (s == null) {
break;
}
stringBuffer.append(s);
}
}
System.out.println(System.currentTimeMillis() - l + "毫秒 " + stringBuffer.length());
}
今度は、この仕事をするために複数のスレッドを使用することができ、各スレッドNテキストは、合併を完成させます。
まずRecursiveTask担当者が値を返す使用し、タスクを送信することにより提出し、あなたが戻り値タスクRecursiveActionを使用することはできません、ファイルの数を直接読み取ることがときに、2つのサブを作成し、二つに一覧で、それ以外の場合は、2未満読みますタスク、2つ以上に割り当てられた2つのサブタスクの数は、その後、フォークオープンタスク(キュー内のジョブにタスクを追加)を呼び出し、2に従ったが、タスクは彼が値を返すようにするために参加することで、待機して、開いている場合()メソッド。
private static void testForkJoin() throws ExecutionException, InterruptedException {
long l = System.currentTimeMillis();
ForkJoinPool forkJoinPool = new ForkJoinPool();
List<File> files = new ArrayList<>();
for (int i = 0; i < 10; i++) {
files.add(new File("/home/cookie", i + ".txt"));
}
ForkJoinTask<StringBuffer> submit = forkJoinPool.submit(new MyTask(files));
System.out.println(System.currentTimeMillis() - l + "毫秒 " + submit.get().length(
}
static class MyTask extends RecursiveTask<StringBuffer> {
List<File> files;
public MyTask(List<File> files) {
this.files = files;
}
@Override
protected StringBuffer compute() {
if (files.size() <= 2) {
StringBuffer stringBuffer = new StringBuffer();
for (int i = 0; i < files.size(); i++) {
File file = files.get(i);
try {
FileReader fileReader = new FileReader(file);
BufferedReader bufferedReader = new BufferedReader(fileReader);
while (true) {
String s = bufferedReader.readLine();
if (s == null) {
break;
}
stringBuffer.append(s);
}
} catch (IOException e) {
e.printStackTrace();
}
}
return stringBuffer;
}
int pos1 = files.size() / 2;
int pos2 = pos1;
MyTask myTask1 = new MyTask(files.subList(0, pos1));
MyTask myTask2 = new MyTask(files.subList(pos2, files.size()));
myTask1.fork();
myTask2.fork();
return myTask1.join().append(myTask2.join());
}
}
上記の手順を実行して、わずか3ミリ秒かかります。