我眼中的并发编程——Fork/Join模型

简介

Fork/Join模型是ExecutorService的接口实现,可以帮助你利用多个处理器。它被设计用可以递归地分解成更小的任务,目的是所有可用的处理能力来提高应用程序性能,与分而治之思路类似。

与任何一个ExecutorService实现一样,Fork/Join模型将任务分配到线程池中的工作线程中。但Fork/Join框架与其他的区别是采用了工作窃取算法,工作线程任务完成后可能会从仍然忙碌的其他线程窃取任务。

Fork/Join模型的核心是ForkJoinPool,该类的扩展AbstractExecutorServiceForkJoinPool实现核心工作窃取算法,可以执行ForkJoinTask任务。

基本使用

使用Fork/Join模型第一步应该编写核心任务代码。大题逻辑如下:

if(我的任务足够小){
     直接工作
}else{
     任务划分成两份,
      执行并等待结果。
}

把这段代码封装到一个ForkJoinTask的子类中。通常做法是继承 RecursiveTask或 RecursiveAction

RecursiveTask:有返回值。
RecursiveAction:无返回值。

代码样例

package com.itunic.concurrent;

import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;

public class CountTask extends RecursiveTask<Long> {

 private static final long serialVersionUID = 1L;
 private long start;
 private long end;
 // 区分任务颗粒度
 private static final int THRESHOLD = 2;

 public CountTask(long start, long end) {
 this.start = start;
 this.end = end;
    }

 @Override
 protected Long compute() {
 long sum = 0;
 boolean canCompute = (end - start) <= THRESHOLD;
 // 判断任务的颗粒度是否足够小
 if (canCompute) {
 for (long i = start; i < end; i++) {
                sum += i;
            }
        } else {
 // 将数据切分
 long middle = (start + end) / 2;
            CountTask task1 = new CountTask(start, middle);
            CountTask task2 = new CountTask(middle, end);
 // 发起两个线程任务
            invokeAll(task1, task2);
 // 等待线程返回结果
 long result1 = task1.join();
 long result2 = task2.join();
            sum = result1 + result2;
        }
 return sum;
    }

 public static void main(String[] args) throws InterruptedException, ExecutionException {
        ForkJoinPool pool = new ForkJoinPool();
        ForkJoinTask<Long> future = pool.submit(new CountTask(1, 10));
        System.out.printf("统计结果为:%s",future.get());

    }

}

我的博客即将搬运同步至腾讯云+社区,邀请大家一同入驻:https://cloud.tencent.com/developer/support-plan?invite_code=2head3ycz2qss

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏架构师之旅

3个面试中遇到的问题《JAVA面试题》

面试官:“一个http 请求,接受json数组,数组内容是id,返回用户信息,在测试上是ok的,到预生产就报错了,可能是什么问题?” 我想了想说:“代码一致吗?...

2445
来自专栏三丰SanFeng

无锁编程(四) - CAS与ABA问题

CAS 一般采用原子级的read-modify-write原语来实现Lock-Free算法,其中LL和SC是Lock-Free理论研究领域的理想原语,但实现这些...

4479
来自专栏月牙寂

[以太坊源代码分析] VI. 基于p2p的底层通信(上篇)

本文转载来源自:http://blog.csdn.net/teaspring/article/details/78455046 感谢原作者teaspring...

4787
来自专栏ImportSource

一次与印度兄弟就Java10中的Thread-Local Handshakes的探讨

背景 Java10引入了Thread Local Handshake功能。对此功能本人看了JEP312以后还是没有一个比较清晰的认识。为此,问了一些国内的JVM...

3969
来自专栏吉浦迅科技

DAY6:阅读 CUDA C编程接口之CUDA C runtime

902
来自专栏大数据钻研

金三银四跳槽季,上周刚面试回来后的面试总结,想进BAT必看

上周陪同之前一起工作的同事去面试(乔治,小袁,鹏飞(面试人)),第一站是去深圳,第二站上海,第三站杭州。面试什么公司我在这里就不多说了,你们知道是一线公司就行。...

3437
来自专栏云计算与大数据

How to Monitor Zookeeper

As per previous articles, our general rule of thumb is “collect all possible/rea...

824
来自专栏码匠的流水账

JCTools简介

JCTools是一款对jdk并发数据结构进行增强的并发工具,主要提供了map以及queue的增强数据结构。原来netty还是自己写的MpscLinkedQueu...

391
来自专栏坚毅的PHP

zookeeper学习系列:三、利用zookeeper做选举和锁

之前只理解zk可以做命名,配置服务,现在学习下他怎么用作选举和锁,进一步还可构建master-slave模式的分布式系统。 为什么叫Zoo?“因为要协调的分布式...

3144
来自专栏岑玉海

Spark源码系列(一)spark-submit提交作业过程

前言 折腾了很久,终于开始学习Spark的源码了,第一篇我打算讲一下Spark作业的提交过程。 ? 这个是Spark的App运行图,它通过一个Driver来和集...

3946

扫码关注云+社区