一、ForkJoin简介
- ForkJoin是JDK1.7引入的一钟新的并发框架,主要用于实现 分而治之 的算法。
- 简单的讲就是,把一个大任务分割成若干个小任务,最终汇总每个小任务结果后得到大任务的计算结果。
二、如何使用
- 只需要两个类即可:
- ForkJoinPool
ForkJoinPool
它和ThreadPoolExecutor
一样,也实现了Executor和ExecutorService接口。
- 它使用了一个无限队列来保存需要执行的任务,如果没有像构造函数中传入线程数量,则默认使用计算机CPU数量为线程数量
- 它是来运行 ForkJoinTask 任务的。
- ForkJoinTask
- ForkJoinTask就是我们要分割的任务实现
- 框架帮我们封装好了两个实现类:
- RecursiveAction 用于没有返回结果的任务
- RecursiveTask 用于有返回结果的任务
- 然后我们还要设置一个任务分割的阈值
三、代码案例实现
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72
|
@Slf4j public class ForkJoinDemo extends RecursiveTask<Long> {
private static final int threshold = 10;
private long start; private long end;
public ForkJoinDemo(long start, long end) { this.start = start; this.end = end; }
@Override protected Long compute() { long sum = 0; if(end-start>threshold){ long middle = (end+start)/2; ForkJoinDemo leftForkJoin = new ForkJoinDemo(start,middle); ForkJoinDemo rightForkJoin = new ForkJoinDemo(middle+1,end);
leftForkJoin.fork(); rightForkJoin.fork();
Long leftSum = leftForkJoin.join(); Long rightSum = rightForkJoin.join(); sum = leftSum+rightSum; }else{ for (long i = start; i <= end; i++) { sum+=i; } } return sum; }
public static void main(String[] args) throws ExecutionException, InterruptedException { ForkJoinPool forkJoinPool = new ForkJoinPool(); ForkJoinDemo forkJoinDemo = new ForkJoinDemo(15,50); ForkJoinTask<Long> forkJoinTask = forkJoinPool.submit(forkJoinDemo); Long sum = forkJoinTask.get(); if (forkJoinTask.isCompletedAbnormally()) { log.error("forkJoin 发生了异常:",forkJoinDemo.getException()); } System.out.println("结果="+sum); forkJoinPool.shutdown(); } }
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67
|
@Slf4j public class ForkJoinListDemo extends RecursiveTask<Long> {
private static final int threshold = 10;
private List<Integer> list;
public ForkJoinListDemo(List<Integer> list) { this.list = list; }
@Override protected Long compute() { long sum = 0; if(!ObjectUtils.isEmpty(list) && list.size()>threshold){ int middle = list.size() / 2; List<Integer> leftList = list.subList(0, middle); List<Integer> rightList = list.subList(middle, list.size()); ForkJoinListDemo leftForkJoin = new ForkJoinListDemo(leftList); ForkJoinListDemo rightForkJoin = new ForkJoinListDemo(rightList);
leftForkJoin.fork(); rightForkJoin.fork();
Long leftSum = leftForkJoin.join(); Long rightSum = rightForkJoin.join(); sum = leftSum+rightSum; }else{ sum=list.stream().mapToInt(i -> i).sum(); } return sum; }
public static void main(String[] args) { List<Integer> list = new ArrayList<>(); for (int i = 15; i <= 50; i++) { list.add(i); } ForkJoinPool forkJoinPool = new ForkJoinPool(); ForkJoinListDemo forkJoinDemo = new ForkJoinListDemo(list); Long sum = forkJoinPool.invoke(forkJoinDemo); System.out.println("结果="+sum); forkJoinPool.shutdown(); } }
|
- 上面的示例代码算是入门版的ForkJoin,只有理解掌握了,我们就可以写出复杂的ForkJoin了。
您的打赏,是我创作的动力!不给钱?那我只能靠想象力充饥了。
微信支付
支付宝