线程的并发工具类 --- Fork-Join

Fork-Join 


java下多线程的开发可以我们自己启用多线程,线程池,还可以使用forkjoin, forkjoin 可以让我们不去了解诸如 Thread,Runnable 等相关的知识,只要遵循 forkjoin 的开发模式,就可以写出很好的多线程并发程序,

分而治之同时 forkjoin 在处理某一类问题时非常的有用,哪一类问题?

分而治之的问题。

十大计算机经典算法:快速排序、堆排序、归并排序、二分查找、线性查找、 深度优先、广度优先、Dijkstra、动态规划、朴素贝叶斯分类,

有几个属于分而治之?

3 个,快速排序、归并排序、二分查找,还有大数据中 M/R 都是。 分治法的设计思想是:将一个难以直接解决的大问题,分割成一些规模较小 的相同问题,以便各个击破,分而治之。

分治策略是:对于一个规模为 n 的问题,若该问题可以容易地解决(比如说 规模 n 较小)则直接解决,否则将其分解为 k 个规模较小的子问题,这些子问题 互相独立且与原问题形式相同(子问题相互之间有联系就会变为动态规范算法), 递归地解这些子问题,然后将各子问题的解合并得到原问题的解。这种算法设计 策略叫做分治法。

归并排序( 降 序 )示例


1.先将数组划分为左右两个子表

2.然后继续左右两个子表拆分

3.对最后的拆分的子表,两两进行排序

4.对有序的子表进行排序和比较合并

5.对合并后的子表继续比较合并

Fork-Join原理

工作密取

即当前线程的 Task 已经全被执行完毕,则自动取到其他线程的 Task 池中取 出 Task 继续执行。

 ForkJoinPool 中维护着多个线程(一般为 CPU 核数)在不断地执行 Task,每 个线程除了执行自己职务内的 Task 之外,还会根据自己工作线程的闲置情况去 获取其他繁忙的工作线程的 Task,如此一来就能能够减少线程阻塞或是闲置的时 间,提高 CPU 利用率。

Fork-Join实战

Fork-Join使用的标准范式

我们要使用 ForkJoin 框架,必须首先创建一个 ForkJoin 任务。它提供在任务 中执行 fork 和 join 的操作机制,通常我们不直接继承 ForkjoinTask 类,只需要直 接继承其子类。 

1.RecursiveAction,用于没有返回结果的任务 

2.RecursiveTask,用于有返回值的任务 

task 要通过 ForkJoinPool 来执行,使用 submit 或 invoke/execute  提交,两者的区 别是:invoke 是同步执行,调用之后需要等待任务完成,才能执行后面的代码; submit/execute 是异步执行。 

join()和 get 方法当任务完成的时候返回计算结果。

join()与get()区别?

方法join()与get()虽然都能取得计算后的结果值,但它们之间还是在出现异常时有处理上的区别

使用get()方法执行任务时,当子任务出现异常时可以在main主线程中进行捕获。方法join()遇到异常直接抛出

在我们自己实现的 compute 方法里,首先需要判断任务是否足够小,如果 足够小就直接执行任务。如果不足够小,就必须分割成两个子任务,每个子任务在调用 invokeAll 方法时,又会进入 compute 方法,看看当前子任务是否需要继 续分割成孙任务,如果不需要继续分割,则执行当前子任务并返回结果。使用 join 方法会等待子任务执行完并得到其结果。

Fork-Join的同步用法和异步用法

public class MakeArray {

//数组长度

    public static final int ARRAY_LENGTH =40000000;

public final static int THRESHOLD =47;

public static int[] makeArray() {

//new一个随机数发生器

        Random r =new Random();

int[] result =new int[ARRAY_LENGTH];

for (int i =0; i

//用随机数填充数组

            result[i] = r.nextInt(ARRAY_LENGTH *3);

}

return result;

}

}

ForkJoin执行累加

public class SumArray {

private static class SumTaskextends RecursiveTask{

/*阈值*/

        private final static int THRESHOLD = MakeArray.ARRAY_LENGTH/10;

private int[]src;

private int fromIndex;

private int toIndex;

public SumTask(int[] src,int fromIndex,int toIndex) {

this.src = src;

this.fromIndex = fromIndex;

this.toIndex = toIndex;

}

@Override

        protected Integer compute() {

/*任务的大小是否合适*/

            if (toIndex -fromIndex

//                System.out.println(" from index = "+fromIndex

//                        +" toIndex="+toIndex);

                int count =0;

for(int i=fromIndex;i<=toIndex;i++){

SleepTools.ms(1);

count = count +src[i];

}

return count;

}else{

//fromIndex....mid.....toIndex

                int mid = (fromIndex+toIndex)/2;

SumTask left =new SumTask(src,fromIndex,mid);

SumTask right =new SumTask(src,mid+1,toIndex);

invokeAll(left,right);

return left.join()+right.join();

}

}

}

public static void main(String[] args) {

int[] src = MakeArray.makeArray();

/*new出池的实例*/

        ForkJoinPool pool =new ForkJoinPool();

/*new出Task的实例*/

        SumTask innerFind =new SumTask(src,0,src.length-1);

long start = System.currentTimeMillis();

pool.invoke(innerFind);

//System.out.println("Task is Running.....");

        System.out.println("The count is "+innerFind.join()

+" spend time:"+(System.currentTimeMillis()-start)+"ms");

}

}

遍历指定目录(含子目录)找寻指定类型文件

public class FindDirsFilesextends RecursiveAction {

private Filepath;

public FindDirsFiles(File path) {

this.path = path;

}

@Override

    protected void compute() {

List subTasks =new ArrayList<>();

File[] files =path.listFiles();

if (files!=null){

for (File file : files) {

if (file.isDirectory()) {

// 对每个子目录都新建一个子任务。

                    subTasks.add(new FindDirsFiles(file));

}else {

// 遇到文件,检查。

                    if (file.getAbsolutePath().endsWith("txt")){

System.out.println("文件:" + file.getAbsolutePath());

}

}

}

if (!subTasks.isEmpty()) {

// 在当前的 ForkJoinPool 上调度所有的子任务。

                for (FindDirsFiles subTask :invokeAll(subTasks)) {

subTask.join();

}

}

}

}

public static void main(String [] args){

try {

// 用一个 ForkJoinPool 实例调度总任务

            ForkJoinPool pool =new ForkJoinPool();

FindDirsFiles task =new FindDirsFiles(new File("F:/"));

/*异步提交*/

            pool.execute(task);

/*主线程做自己的业务工作*/

            System.out.println("Task is Running......");

Thread.sleep(1);

int otherWork =0;

for(int i=0;i<100;i++){

otherWork = otherWork+i;

}

System.out.println("Main Thread done sth......,otherWork="

                    +otherWork);

task.join();//阻塞方法

            System.out.println("Task end");

}catch (Exception e) {

// TODO Auto-generated catch block

            e.printStackTrace();

}

}

}


以上内容仅代表个人学习的见解,希望可以为大家提供一个学习参考

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,053评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,527评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,779评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,685评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,699评论 5 366
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,609评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,989评论 3 396
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,654评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,890评论 1 298
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,634评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,716评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,394评论 4 319
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,976评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,950评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,191评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 44,849评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,458评论 2 342

推荐阅读更多精彩内容