forkjoin和forkjoinpool讲解
背景
对于java开发从业人员来说,并发编程是绕不开的话题,juc并发包下提供了一系列多线程场景解决方案。
随着jdk1.8的普及,多线程处理问题,除了使用使用线程池(ExecutorService),很多人选择了parallelStream() 并行流,底层使用forkjoin实现并行处理。
那么并行和并发又有什么区别?究竟改如何选择?滥用时又会有什么影响?
这些问题我分以下几篇文章进行详细说明:
1. 多线程并发和并行的区别
2. parallelStream()并行滥用的后果
3. forkjoin和forkjoinpool讲解 (本文)
4. 线程池正确用法
为什么需要forkjoin
两个好处ThreadPool无法替代
- 线程私有队列,更节省资源
- 工作窃取机制,均衡利用cpu
用下面这个例子说明以上两点,如果将一段计算拆分成如下16段进行多线程计算。
- 如果用多线程递归拆分,需要16个线程,而且当cpu核数只有4核时,会存在cpu切换的额外消耗;用forkjoin默认使用cpu相同核数的线程,将任务放入队列进行并行计算。
- 如果使用多线程计算,如果某个线程分到的任务执行比较慢,其他线程先执行完,就会有额外的cpu浪费。如果用forkjoin,先执行完的线程,会到慢的线程队列中窃取任务,均匀利用cpu。
先看代码
看原理之前,先简单的看forkjoin例子
package com.chainup.forkjoin;
import java.util.concurrent.*;
/**
* @Author zhongjingyun
* 通过forkjoin完成1~1000累加
* @Date 2020/9/8 下午11:18
**/
public class ForkJoinDemo {
public static void main(String[] args) throws Exception{
//使用ForkJoinPool来执行任务
ForkJoinPool forkJoinPool = ForkJoinPool.commonPool();