Java?并發(fā)編程之ForkJoin框架
1、什么是ForkJoin框架
ForkJoin框架是java的JUC包里提供的,用于處理一些比較繁重的任務(wù),會(huì)將這個(gè)大任務(wù)分為多個(gè)小任務(wù),多個(gè)小任務(wù)處理完成后會(huì)將結(jié)果匯總給Result,體現(xiàn)的是一種“分而治之”的思想。第一步,拆分fork任務(wù),將大任務(wù)分為多個(gè)小任務(wù);第二步,歸并join,會(huì)將小任務(wù)的處理結(jié)果進(jìn)行歸并為一個(gè)結(jié)果。

2、ForkJoinTask
ForkJoinTask是ForkJoin框架的提供的任務(wù)API,F(xiàn)orkJoinTask是一個(gè)抽象類,有兩個(gè)主要的實(shí)現(xiàn)類,RecursiveTask和RecursiveAction,其中RecursiveTask和RecursiveAction的主要區(qū)別是,RecursiveAction沒有返回值,而RecursiveTask是有返回值的

3、ForkJoinPool
ForkJoinPool類是forkjoin框架的線程池實(shí)現(xiàn),基于ExecutorService接口。這個(gè)線程池是jdk1.7才加入的,用于管理線程,執(zhí)行forkjoin的任務(wù)。對(duì)于線程池的使用,我們使用ThreadPoolExecutor比較多,可以在idea里看一下uml類圖,可以看出ForkJoinPool和ThreadPoolExecutor實(shí)現(xiàn)差不多的。

ForkJoinPool() ForkJoinPool(int parallelism) ForkJoinPool(int parallelism, ForkJoinWorkerThreadFactory factory, UncaughtExceptionHandler handler, boolean asyncMode)
幾個(gè)重要的參數(shù):
parallelism:并行度,并行執(zhí)行線程,可用指定,也可以不指定,不指定的情況,是根據(jù)cpu核數(shù)創(chuàng)建可用的線程ForkJoinWorkerThreadFactory:創(chuàng)建線程的工廠實(shí)現(xiàn)UncaughtExceptionHandler:因?yàn)槲粗惓V袛嗟幕卣{(diào)處理asyncMode:是否異步,默認(rèn)情況是false
使用時(shí)候,可以直接創(chuàng)建ForkJoinPool,可以不傳參,不傳參的情況,默認(rèn)指定的線程并行數(shù)為Runtime.getRunTime().availableProcessors();,表示根據(jù)cpu核數(shù)創(chuàng)建可用線程數(shù)
ForkJoinPool forkJoinPool = new ForkJoinPool(); ArraySortTask task = new ArraySortTask(array , 0 , size); forkJoinPool.submit(task); task.get();
也是可用傳參,對(duì)并行度進(jìn)行指定的public ForkJoinPool(int parallelism), parallelism并行度,并行執(zhí)行幾個(gè)線程
將forkjoin任務(wù)加入到FrokJoinPool線程池有幾種方式
execute():調(diào)用其 fork 方法在多個(gè)線程之間拆分工作。invoke():在ForkJoinPool線程池上調(diào)用invoke方法submit():返回一個(gè)Future對(duì)象,F(xiàn)uture可以進(jìn)行監(jiān)控,任務(wù)完成后返回結(jié)果
4、打印斐波那契數(shù)列
ForkJoin框架可以用于一些遞歸遍歷的場(chǎng)景,對(duì)于斐波那契數(shù)列,你可以比較熟悉,因?yàn)樵诿嬖囍杏袝r(shí)候經(jīng)常問到,斐波那契數(shù)列的特點(diǎn)就是最后一項(xiàng)的結(jié)果等于前面兩項(xiàng)的和
package com.example.concurrent.forkjoin;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.ForkJoinTask;
import java.util.concurrent.RecursiveTask;
/**
* <pre>
* 斐波那契數(shù)列
* </pre>
* <p>
* <pre>
* @author nicky.ma
* 修改記錄
* 修改后版本: 修改人: 修改日期: 2021/10/12 16:22 修改內(nèi)容:
* </pre>
*/
public class Fibonacci extends RecursiveTask<Integer>{
private int n;
public Fibonacci(int n) {
this.n = n;
}
@Override
protected Integer compute() {
if (n <= 1)
return n;
Fibonacci f1 = new Fibonacci(n - 1);
f1.fork();
Fibonacci f2 = new Fibonacci(n - 2);
f2.fork();
return f1.join() + f2.join();
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
ForkJoinPool pool = new ForkJoinPool();
for (int i = 0; i< 10; i++) {
ForkJoinTask task = pool.submit(new Fibonacci(i));
System.out.println(task.get());
}
}
}
5、ForkJoin歸并排序
面試題:快速實(shí)現(xiàn)對(duì)一個(gè)長度百萬的數(shù)組的排序
難點(diǎn):可以使用歸并排序,多線程如何組織實(shí)現(xiàn)歸并排序
package com.example.concurrent.forkjoin;
import java.util.Arrays;
import java.util.Random;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveAction;
/**
* <pre>
* 大數(shù)組排序
* </pre>
* <p>
* <pre>
* @author mazq
* 修改記錄
* 修改后版本: 修改人: 修改日期: 2021/10/12 17:04 修改內(nèi)容:
* </pre>
*/
public class ArraySortTask extends RecursiveAction{
final long[] array; final int lo, hi;
ArraySortTask(long[] array, int lo, int hi) {
this.array = array; this.lo = lo; this.hi = hi;
}
ArraySortTask(long[] array) { this(array, 0, array.length); }
@Override
protected void compute() {
if (hi - lo < THRESHOLD)
// 少于閥值,使用Arrays.sort 快排
sortSequentially(lo, hi);
else {
/* 歸并排序 */
// 取中間值
int mid = (lo + hi) >>> 1;
// 拆分任務(wù)
invokeAll(new ArraySortTask(array, lo, mid),
new ArraySortTask(array, mid, hi));
// 歸并結(jié)果
merge(lo, mid, hi);
}
}
// implementation details follow:
static final int THRESHOLD = 1000;
void sortSequentially(int lo, int hi) {
Arrays.sort(array, lo, hi);
}
void merge(int lo, int mid, int hi) {
long[] buf = Arrays.copyOfRange(array, lo, mid);
for (int i = 0, j = lo, k = mid; i < buf.length; j++)
array[j] = (k == hi || buf[i] < array[k]) ?
buf[i++] : array[k++];
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
int size = 10_000;
long[] array = new long[size];
Random random = new Random();
for (int i = 0; i< size; i++) {
array[i] = random.nextInt();
}
ForkJoinPool forkJoinPool = new ForkJoinPool();
ArraySortTask task = new ArraySortTask(array , 0 , size);
forkJoinPool.submit(task);
task.get();
for (long a : array) {
System.out.println(a);
}
}
}
總結(jié)
本篇文章就到這里了,希望能夠給你帶來幫助,也希望您能夠多多關(guān)注腳本之家的更多內(nèi)容!
相關(guān)文章
java設(shè)計(jì)模式之單例模式學(xué)習(xí)
單例對(duì)象(Singleton)是一種常用的設(shè)計(jì)模式。在Java應(yīng)用中,單例對(duì)象能保證在一個(gè)JVM中,該對(duì)象只有一個(gè)實(shí)例存在2014-01-01
Spring?Boot?整合持久層之Spring Data JPA
在介紹Spring Data JPA的時(shí)候,我們首先認(rèn)識(shí)下Hibernate。Hibernate是數(shù)據(jù)訪問解決技術(shù)的絕對(duì)霸主,使用O/R映射技術(shù)實(shí)現(xiàn)數(shù)據(jù)訪問,O/R映射即將領(lǐng)域模型類和數(shù)據(jù)庫的表進(jìn)行映射,通過程序操作對(duì)象而實(shí)現(xiàn)表數(shù)據(jù)操作的能力,讓數(shù)據(jù)訪問操作無須關(guān)注數(shù)據(jù)庫相關(guān)的技術(shù)2022-08-08
dubbo如何實(shí)現(xiàn)consumer從多個(gè)group中調(diào)用指定group的provider
這篇文章主要介紹了dubbo如何實(shí)現(xiàn)consumer從多個(gè)group中調(diào)用指定group的provider問題,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2023-03-03
在IntelliJ IDEA中.idea文件是什么可以刪除嗎
相信有很多小伙伴,在用idea寫java代碼的時(shí)候,創(chuàng)建工程總是會(huì)出現(xiàn).idea文件,該文件也從來沒去打開使用過,那么它在我們項(xiàng)目里面,扮演什么角色,到底能不能刪除它呢?這篇文章主要介紹了在IntelliJ IDEA中.idea文件是什么可以刪除嗎,需要的朋友可以參考下2024-01-01
springmvc無法訪問/WEB-INF/views下的jsp的解決方法
本篇文章主要介紹了springmvc無法訪問/WEB-INF/views下的jsp的解決方法,非常具有實(shí)用價(jià)值,需要的朋友可以參考下2017-10-10
Java使用MySQL實(shí)現(xiàn)連接池代碼實(shí)例
這篇文章主要介紹了Java使用MySQL實(shí)現(xiàn)連接池代碼實(shí)例,文中通過示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友可以參考下2020-03-03

