# ForkJoinPool

## 如何使用

### 构造方法

Android官方文档中给出了三个构造方法。我们注意到在构造方法中，我们可以设置ForkJoinPool的最大工作线程数、工作线程工厂、拒绝任务的Handler和同步模式。

### 执行任务

ForkJoinPool提供了两套执行任务的API，它们的区别主要是返回的结果类型不同。invoke方法返回执行的结果，而submit方法返回执行的任务。

## 使用示例

### 代码实现

```    CountingTask countingTask = new CountingTask(Environment.getExternalStorageDirectory());
forkJoinPool.invoke(countingTask);

class CountingTask extends RecursiveTask<Integer> {
private File dir;

public CountingTask(File dir) {
this.dir = dir;
}

@Override
protected Integer compute() {
int count = 0;

File files[] = dir.listFiles();
if(files != null){
for (File f : files){
if(f.isDirectory()){
// 对每个子目录都新建一个子任务。
CountingTask countingTask = new CountingTask(f);
countingTask.fork();
count += countingTask.join();

}else {
Log.d("tag" , "current path = "+f.getAbsolutePath());
count++;
}
}
}

return count;
}
}         ```

## 再来个例子

N项的Fibonacci数列求和，我们不再只能仰仗单个线程为我们执行任务。

```package com.example;

import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.RecursiveTask;

public class MyClass {

static int computeCount = 0;

static class Fibonacci extends RecursiveTask<Integer> {
int n;

Fibonacci(int n) {
this.n = n;
}

@Override
protected Integer compute() {
computeCount ++;
System.out.printf("Current thread is " + Thread.currentThread()
+ "\n n = " + n + "\n");

if (n <= 2)
return 1;
Fibonacci f1 = new Fibonacci(n - 1);
f1.fork();

try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

Fibonacci f2 = new Fibonacci(n - 2);
f2.fork();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.printf("wati temp answer is :" + n + "\n");
int answer = f1.join() + f2.join();
System.out.printf("temp answer is :" + answer  + ",  n is :" +n +"\n");
return answer;
}
}

public static void main(String[] args)  {
ForkJoinPool pool = new ForkJoinPool(2);
Fibonacci task = new Fibonacci(5);
int answer = 0;
answer = pool.invoke(task);
System.out.printf("Hello answer is :" + answer +  " , compute count is :" + computeCount);
}
}```

## 结语

0 条评论

• ### Thread备忘录

start()用来启动一个线程，当调用start方法后，系统才会开启一个新的线程来执行用户定义的子任务，在这个过程中，会为相应的线程分配需要的资源。

• ### 指北 | 谈谈ForkJoin框架的设计与实现

相对于串行计算，并行计算可以划分成时间并行和空间并行。时间并行即指令流水化，也就是流水线技术。比如说生产一辆小汽车，有特定的轮子车间/发动机车间，同时进行各自的...

• ### 多线程编程学习七( Fork/Join 框架).

使用 java8 lambda 表达式大半年了，一直都知道底层使用的是 Fork/Join 框架，今天终于有机会来学学 Fork/Join 框架了。

• ### Java并发编程的艺术(十一)——线程池(2)

Executor两级调度模型 ? 在HotSpot虚拟机中，Java中的线程将会被一一映射为操作系统的线程。 在Java虚拟机层面，用户将多个任务提...

• ### BAT美团滴滴java面试大纲（带答案版）之四：多线程Lock

继续面试大纲系列文章。 　　这是多线程的第二篇。 　　多线程就像武学中对的吸星大法，理解透了用好了可以得道成仙，俯瞰芸芸众生；而滥用则会遭其反噬。 　　在多线程...

• ### 驾驭Java线程池：定制与扩展

Executor框架可以帮助将任务的提交和任务的执行解耦合，用户只需要将任务提交给Executor之后，其自会按照既定的执行策略来执行任务。但是要注意并不是所有...

• ### (83) 并发总结 / 计算机程序的思维逻辑

从65节到82节，我们用了18篇文章讨论并发，本节进行简要总结。 多线程开发有两个核心问题，一个是竞争，另一个是协作。竞争会出现线程安全问题，所以，本节首先总结...

• ### 女同事问狗哥什么是线程池的阻塞队列？

如图所示，线程池的内部结构主要由线程池管理器、工作线程、任务队列以及任务四部分组成。