目录
ForkJoinTask
ForkJoinTask类是由ForkJoinPool类执行的,虽然ForkJoinPool也可以执行Runnable和Callable,但只有ForkJoinTask可以利用fork/join框架的优点(任务窃取算法)。
前面介绍过ForkJoinTask的三个子类实现:
- RecursiveAction,任务不返回执行结果。
- RecursiveTask,任务返回一个执行结果
- CountedCompleter类,所有子任务执行完毕后启动一个完成方法。
简单说明
由于上述3个子类的exec()方法都使用了final关键字,无法在其基础上进行拓展。于是我们要另外继承ForkJoinTask,自定义一个类似于RecursiveAction和RecursiveTask的抽象类。然后定义抽象的compute()方法由任务类对其进行实现(编写任务逻辑)。
一、主程序
package xyz.jangle.thread.test.n8_8.forkjointask;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.TimeUnit;
/**
* 8.8、自定义fork/join任务抽象类
* @author jangle
* @email jangle@jangle.xyz
* @time 2020年10月4日 下午2:33:28
*
*/
public class M {
public static void main(String[] args) throws Exception {
int array[] = new int[10000];
var pool = new ForkJoinPool();
var task = new Task("Taskk", array, 0, array.length);
pool.execute(task);
pool.shutdown();
pool.awaitTermination(1, TimeUnit.DAYS);
System.out.println("Main:End...");
}
}
二、自定义任务抽象类
package xyz.jangle.thread.test.n8_8.forkjointask;
import java.util.Date;
import java.util.concurrent.ForkJoinTask;
/**
* 自定义用于fork/join框架中的任务抽象类
*
* @author jangle
* @email jangle@jangle.xyz
* @time 2020年10月6日 上午10:31:55
*
*/
public abstract class MyWorkerTask extends ForkJoinTask<Void> {
private String name;
private static final long serialVersionUID = 1L;
public MyWorkerTask(String name2) {
this.name = name2;
}
@Override
public Void getRawResult() {
return null;
}
@Override
protected void setRawResult(Void value) {
}
@Override
protected boolean exec() {
var startDate = new Date();
compute();
var endDate = new Date();
long diff = endDate.getTime() - startDate.getTime();
System.out.println("MyWorkerTask: " + name + ":" + diff);
return true;
}
/**
* 用于子类重写
*/
protected abstract void compute();
public String getName() {
return name;
}
}
三、解决问题的任务类
package xyz.jangle.thread.test.n8_8.forkjointask;
/**
* 定义一个解决问题的任务(继承fork/join抽象类)
*
* @author jangle
* @email jangle@jangle.xyz
* @time 2020年10月6日 上午10:37:43
*
*/
@SuppressWarnings("serial")
public class Task extends MyWorkerTask {
private int array[];
private int start, end;
public Task(String name, int[] array, int start, int end) {
super(name);
this.array = array;
this.start = start;
this.end = end;
}
@Override
protected void compute() {
if (end - start > 100) {
int mid = (start + end) / 2;
var t1 = new Task(getName(), array, start, mid);
var t2 = new Task(getName(), array, mid, end);
invokeAll(t1, t2);
} else {
for (int i = start; i < end; i++) {
array[i]++;
}
}
try {
Thread.sleep(50);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
四、执行结果
MyWorkerTask: Taskk,51
MyWorkerTask: Taskk,1572
MyWorkerTask: Taskk,51
MyWorkerTask: Taskk,1622
MyWorkerTask: Taskk,151
MyWorkerTask: Taskk,1622
MyWorkerTask: Taskk,152
MyWorkerTask: Taskk,355
MyWorkerTask: Taskk,1673
MyWorkerTask: Taskk,304
MyWorkerTask: Taskk,405
MyWorkerTask: Taskk,1014
MyWorkerTask: Taskk,1825
MyWorkerTask: Taskk,1875
MyWorkerTask: Taskk,1927
Main:End...
本文介绍了如何自定义ForkJoinTask的抽象类`MyWorkerTask`,并创建了一个名为`Task`的具体任务类来解决特定问题。任务类通过检查任务大小来决定是否拆分任务,实现了并行计算。最后展示了任务执行的时间消耗和结果。

1269

被折叠的 条评论
为什么被折叠?



