1.ForkJoinとは何ですか
Java 7は、新しいFork / Joinスレッドプールの導入を開始しました。これにより、大きなタスクを複数の小さなタスクに分割して並列実行し、各小さなタスクの実行結果を集約して、大きなタスクの最終結果を取得できます。
Fork / Joinタスクの原則:タスクが十分に小さいかどうかを判断し、十分に小さい場合は直接計算します。そうでない場合は、いくつかの小さなタスクに分割して個別に計算します。
fork():在当前线程运行的线程池中创建一个子任务;
join():模块子任务完成的时候返回任务结果;
2.仕事の盗難
大きなタスクは独立したサブタスクに分割され、サブタスクは異なるキューに配置され、スレッドBが自分のキューに割り当てられたタスクを最初に実行すると仮定して、キュー内のタスクを実行するためにキューごとにスレッドが作成されます。時間、スレッドに対応するキューで実行されるのを待っているタスクがある場合、アイドル状態のスレッドBはスレッドAのキューでタスクの実行を盗み、スレッドBと盗まれたタスクスレッドAの間の競合を減らします。タスクを盗むとき、タスクを盗むスレッドBはキューの末尾からタスクの実行を取得し、盗まれたタスクスレッドAはキューの先頭からタスクの実行を取得します。
3.アプリケーション例
1〜10000の合計を求めます
//传统思维
public static void main(String[] args) {
int sum = 0;
long start = System.currentTimeMillis();
for (long i = 0; i < 100000000L; i++) {
sum += i;
}
long end = System.currentTimeMillis();
System.out.println(end-start);
}
ForkJoinの使用は、ForkJoinPoolによって実行されます(データ量が多い場合にのみ使用されます)
public class ForkJoinTest {
public static void main(String[] args) throws ExecutionException, InterruptedException {
long start = System.currentTimeMillis();
ForkJoinPool forkJoinPool = new ForkJoinPool();
ForkJoinTask<Long> task = new ForkJoinDemo(1L, 100000000L);
//提交任务
ForkJoinTask<Long> submit = forkJoinPool.submit(task);
Long sum = submit.get();
long end = System.currentTimeMillis();
System.out.println(end-start);
}
}
public class ForkJoinDemo extends RecursiveTask<Long> {
private Long start = 1L;
private Long end = 100000000L;
//临界值
private Long temp = 10000L;
public ForkJoinDemo(Long start, Long end) {
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
if ((end - start) < temp) {
// 基本运算
Long sum = 0L;
for (Long i = start; i <= end; i++) {
sum += i;
}
return sum;
}else {
// ForkJoin
Long middle = (start + end)/2;
// 把一个大任务拆分成两个小任务
ForkJoinDemo task1 = new ForkJoinDemo(start, middle);
// 把任务压入线程队列
task1.fork();
ForkJoinDemo task2 = new ForkJoinDemo(middle+1, end);
task2.fork();
return task1.join()+task2.join();
}
}
}