java 并行框架_java高并发设计(八)--并行框架fork/join

本文介绍Fork/Join并发框架的基本原理及其在Java中的应用。通过对比高并发场景下的处理方式,深入剖析Fork/Join框架如何通过任务拆分与合并提高并发效率。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

互联网一直在说和提到高并发,那什么是高并发,怎么处理高并发?也许每个人都有自己的见解和应对方法,但是总体思想应该及相同的,分而治之,单个服务不发满足时增加服务集群,集群无法满足时考虑拆分,同时选择合适的算法,最终达到解决高并发,但是什么样的级别才能算是高呢?不同的业务也许需求不一样,但是大致还都是相同的,我们最开始使用的处理要素是,200并发,200请求/秒,单机,并且后台也许会有不同的业务逻辑,也许会有其他的复杂计算,这个是根据不同的系统不同的业务而不同设计的。业务你的并发达不到这么高,根据数据的要求,你可能会想到异步处理,或者消息处理来增加并发数。所有的解决方案都不是相同的,只选择适合你们业务的解决方案。

言归正传,这里我们讲的是fork/join的并发处理框架,该框架是是在jdk1.7出现的,如果有人接触过hadoop中的mapreduce,思想是相同的。说起fork/join,我们首先看下该思想的执行操作线路图,这样可以更好的理解该并行计算框架。

5ad63d7ab8a9a4d6157963fe8000e2be.png

上面的图解中有两个最大的世界,fork:将大任务拆分成小任务进行执行;join:将fork出来的小任务的执行结果进行合并,最终实现过程拆分结果合并的操作。

先上说明一些主要的类:ForkJoinTask:顶层设计类,主要是对任务的拆分合并的计算架构。该顶层类有两个核心子类,在java中也是主要继承这两个类来实现并行计算。RecursiveAction:从后缀也可以猜测出,该执行只是动作的执行,没有返回结果。RecursiveTask:执行任务,有返回值,并且是指定类型的返回结果。ForkJoinPool:任务执行线程池,根据自身算法实现线程的高度复用及任务优化。

下面从demo中解析:无返回值的操作

public class ObjectTest {

public static void main(String[] args) throws InterruptedException {

//创建执行线程池

ForkJoinPool pool = new ForkJoinPool();

//提交任务

pool.submit(new ActionTest(0, 200));

pool.awaitTermination(3, TimeUnit.SECONDS);

pool.shutdown();

}

}

//继承无返回值的任务

class ActionTest extends RecursiveAction {

private static final int MAX = 50;

private int start;

private int end;

public ActionTest(int start, int end) {

this.start = start;

this.end = end;

}

@Override

protected void compute() {

if ((end - start) < MAX) {

System.out.println(Thread.currentThread().getName() + "--" + start + "==" + end);

} else {

int middle = (start + end) / 2;

ActionTest up = new ActionTest(start, middle);

ActionTest down = new ActionTest(middle, end);

//继续拆分

up.fork();

down.fork();

}

}

}

源码中的提现:

public class ForkJoinPool extends AbstractExecutorService ,该源码中涉及到很多线程安全和线程池的概念,源码比较多,这里就不一一说明,后面有时间了会拿出来单独说明。

public abstract class RecursiveTask extends ForkJoinTask {

private static final long serialVersionUID = 5232453952276485270L;

/**

* The result of the computation.

*/

V result;

/**

* The main computation performed by this task.

*/

protected abstract V compute();

public final V getRawResult() {

return result;

}

protected final void setRawResult(V value) {

result = value;

}

/**

* Implements execution conventions for RecursiveTask.

*/

protected final boolean exec() {

result = compute();

return true;

}

}

该源码很简单,只是对父类的继承,操作的结果是无返回值的,所以有两个方法直接操作返回,主要提供抽象的compute()方法供子类实现。

有返回值的demo:

public class ObjectTest {

public static void main(String[] args) throws InterruptedException, ExecutionException {

//创建执行线程池

ForkJoinPool pool = new ForkJoinPool();

//提交任务

Future futuer = pool.submit(new TaskTest(0, 200));

System.out.println(futuer.get());

pool.awaitTermination(3, TimeUnit.SECONDS);

pool.shutdown();

}

}

class TaskTest extends RecursiveTask {

private static final int MAX = 50;

private int start;

private int end;

public TaskTest(int start, int end) {

this.start = start;

this.end = end;

}

@Override

protected Integer compute() {

int sum = 0;

if ((end - start) < MAX) {

for (int i = start; i < end; i++) {

sum += i;

}

return sum;

} else {

int middle = (start + end) / 2;

TaskTest up = new TaskTest(start, middle);

TaskTest down = new TaskTest(middle, end);

//继续拆分

up.fork();

down.fork();

return up.join() + down.join();

}

}

}

主要区别在继承的父类和返回值,提现在join方法上。

源码体现:

public abstract class RecursiveTask extends ForkJoinTask {

private static final long serialVersionUID = 5232453952276485270L;

/**

* The result of the computation.

*/

V result;

/**

* The main computation performed by this task.

*/

protected abstract V compute();

public final V getRawResult() {

return result;

}

protected final void setRawResult(V value) {

result = value;

}

/**

* Implements execution conventions for RecursiveTask.

*/

protected final boolean exec() {

result = compute();

return true;

}

}

主要在返回值上的设置会获取

这里先做简单的演示,后面再做深层次的解析和分析

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值