网站首页 > 技术文章 正文
Oracle的官方给出的定义是:Fork/Join框架是一个实现了ExecutorService接口的多线程处理器。它可以把一个大的任务划分为若干个小的任务并发执行,充分利用可用的资源,进而提高应用的执行效率。
主要有两步:1、拆分 2、合并
它的模型大致是这样的:线程池中的每个线程都有自己的工作队列,当自己队列中的任务都完成以后,会从其它线程的工作队列中窃取一个任务执行,这样可以充分利用CPU资源。
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
import java.util.stream.LongStream;
/**
* 场景:求和 (1~1_000_000_000L)
* ForkJoinTask代表一个可以并行、合并的任务。ForkJoinTask是一个抽象类,它有两个抽象子类:
* RecursiveAction和RecursiveTask
*/
@Data
public class ForkJoinDemo extends RecursiveTask<Long> {
private Long start;
private Long end;
private Long splitValue = 100000L;
public ForkJoinDemo(Long start, Long end) {
this.start = start;
this.end = end;
}
@Override
protected Long compute() {
if( (end - start) < splitValue ){
Long temp = 0L;
for (Long i = start ; i <= end ; i++ ){
temp += i;
}
return temp;
}else{
// 求出中间值
Long middle = (end + start) / 2 ;
//任务拆分1
ForkJoinDemo forkJoinLeft = new ForkJoinDemo(start ,middle );
ForkJoinTask<Long> left = forkJoinLeft.fork();
//任务拆分2
ForkJoinDemo forkJoinRight = new ForkJoinDemo( middle+1 ,end );
ForkJoinTask<Long> right = forkJoinRight.fork();
//返回拆分后的结果
return left.join() + right.join();
}
}
/**
* 使用普通循环去计算
*/
public static void test1(){
Long sum = 0L;
Long startTime = System.currentTimeMillis();
for (Long i=0L ; i<=1_000_000_000L ; i++){
sum += i;
}
Long endTime = System.currentTimeMillis();
System.out.println( "计算结果为=" + sum + "使用时间为:"+(endTime-startTime) + "ms");
}
/**
* 使用forkjoin 计算
*/
public static void test2(){
ForkJoinPool forkJoinPool = null;
try {
forkJoinPool = new ForkJoinPool();
Long startTime = System.currentTimeMillis();
ForkJoinDemo forkJoinDemo = new ForkJoinDemo( 0L , 1_000_000_000L );
//submit 为有返回值的提交
ForkJoinTask<Long> forkJoinTask = forkJoinPool.submit( forkJoinDemo );
Long sum = forkJoinTask.get() ;
Long endTime = System.currentTimeMillis();
System.out.println( "计算结果为=" + sum + "使用时间为:"+(endTime-startTime) + "ms");
} catch (Exception e) {
e.printStackTrace();
} finally {
forkJoinPool.shutdown();
}
}
/**
* 使用并行流计算
*/
public static void test3(){
Long startTime = System.currentTimeMillis();
Long sum = LongStream.rangeClosed(0,1_000_000_000).parallel().reduce(0,Long::sum);
Long endTime = System.currentTimeMillis();
System.out.println( "计算结果为=" + sum + "使用时间为:"+(endTime-startTime) + "ms");
}
public static void main(String[] args) {
//普通方式计算方法 5167ms
test1();
//采用forkjoin方式求和 4073ms
test2();
//采用并行流的方式去计算 125ms
test3();
}
}
核心是ForkJoinPool执行者实现了ForkJoinTask接口的实例。ForkJoinTask对象支持创建子任务来等待子任务完成。当一个任务正在等待另一个任务完成并且有待执行的任务时,executor就能够通过”偷取”任务,在内部的线程池里分发任务。
ForkJoinTask对象主要有两个重要的方法:
- fork()方法允许ForkJoinTask任务异步执行
- join()方法允许一个ForkJoinTask等待另一个ForkJoinTask执行完成。
使用fork / join框架应遵循一些指导原则:
- 使用尽可能少的线程池 - 在大多数情况下,最好的决定是为每个应用程序或系统使用一个线程池
- 使用合理的阈值将ForkJoingTask拆分为子任务,如上述代码的splitValue,有优化空间
- 避免在 ForkJoingTask中出现阻塞的IO任务
- 上一篇: 《从实践中学习oracle/SQL》读书笔记 3
- 下一篇: 性能优化技巧:有序归并 有序表的归并算法
猜你喜欢
- 2024-11-05 超实用!手把手入门 MongoDB:这些坑点请一定远离
- 2024-11-05 T-SQL语句基础-增删改查 sql的增删改查指什么
- 2024-11-05 「计算机组成原理」:一文快速了解计算机原理知识点-附思维导图
- 2024-11-05 大数据分析师工程师入门6-HIVE进阶
- 2024-11-05 性能优化技巧:有序归并 有序表的归并算法
- 2024-11-05 《从实践中学习oracle/SQL》读书笔记 3
- 2024-11-05 MySQL常用函数详解,内含示例 mysql常用函数详解,内含示例分析
- 2024-11-05 word中最实用的办公技巧——神奇的F4,让你省时省力,效率翻倍
- 2024-11-05 mysql分组查询详解(group by & having)
- 2024-11-05 「数据分析工具」玩转数据分析中常用的SQL函数
你 发表评论:
欢迎- 621℃几个Oracle空值处理函数 oracle处理null值的函数
- 613℃Oracle分析函数之Lag和Lead()使用
- 602℃0497-如何将Kerberos的CDH6.1从Oracle JDK 1.8迁移至OpenJDK 1.8
- 598℃Oracle数据库的单、多行函数 oracle执行多个sql语句
- 594℃Oracle 12c PDB迁移(一) oracle迁移到oceanbase
- 586℃【数据统计分析】详解Oracle分组函数之CUBE
- 575℃最佳实践 | 提效 47 倍,制造业生产 Oracle 迁移替换
- 563℃Oracle有哪些常见的函数? oracle中常用的函数
- 最近发表
- 标签列表
-
- 前端设计模式 (75)
- 前端性能优化 (51)
- 前端模板 (66)
- 前端跨域 (52)
- 前端缓存 (63)
- 前端aes加密 (58)
- 前端脚手架 (56)
- 前端md5加密 (54)
- 前端路由 (61)
- 前端数组 (73)
- 前端js面试题 (50)
- 前端定时器 (59)
- 前端获取当前时间 (50)
- Oracle RAC (76)
- oracle恢复 (77)
- oracle 删除表 (52)
- oracle 用户名 (80)
- oracle 工具 (55)
- oracle 内存 (55)
- oracle 导出表 (62)
- oracle约束 (54)
- oracle 中文 (51)
- oracle链接 (54)
- oracle的函数 (58)
- 前端调试 (52)
本文暂时没有评论,来添加一个吧(●'◡'●)