package com.yongyou.test;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ForkJoinPool;
import java.util.concurrent.Future;
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.TimeUnit;
import com.sande.user.utils.ThreadPool;
class PrintTask3 extends RecursiveAction {
// 个“小任务”最多只打印50个数
private static final int THRESHOLD = 50;
private int start;
private int end;
// 打印从 start 到 end 的任务
private List<String> list;
public PrintTask3(int start,int end,List<String> list) {
this.start = start;
this.end = end;
this.list = list;
}
//@SuppressWarnings("hiding")
@Override
protected void compute() {
//Integer rest = 100;
List<String> listString = new ArrayList<>();
//int i2=0;
// 当 end 与 start 之间的差小于 THRESHOLD 时,开始打印
if (end - start < THRESHOLD) {
// 业务逻辑写在这个 for 循环中
// 1000个任务,每批50个线程执行,总共需要分成20批,每批都会暂停5毫秒。
// 执行完一批再执行下一批。每一批都是50个线程同时执行,如果每个操作执行要
// 2秒,50个线程同时执行只有大概2秒可以执行完50操作,如果不用线程池串行执行,完成这50个操作就需要
// 需要100秒。
for (int i = start; i<end; i++) {
listString.add(list.get(i));
//System.out.println(Thread.currentThread().getName()
// + "的 i 值:" + i);
System.out.println("输出批次:" + i);
//System.out.println("list.get("+i+"):" + list.get(i));
// 注意:不能在 for 循环中输出了子结果,如果有了这输出语句,就会只输出第一批执行的结果,
// 后面的结果无法再输出
//System.out.println("list.get("+i+"):" + listString.get(i));
/*try {
Thread.sleep(5);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}*/
}
// 注意:每执行完一批就把这批的计算结果存储到LIST中,是要1000个操作全部完成了才会统一取出结果。
// 在这里是单线程输出结果所以是顺序输出
for (String string : listString) {
System.out.println(Thread.currentThread().getName());
System.out.println("计算结果:" + string);
}
} else {
// 当 end 与 start 之间的差大于 THRESHOLD,即要打印数超过 50 个时
// 将大任务分解成两个“小任务”
int middle = (start + end) / 2;
PrintTask3 left = new PrintTask3(start, middle,list);
PrintTask3 right = new PrintTask3(middle, end,list);
// 并行执行两个 "小任务"
//left.fork();
//right.fork();
left.compute();
right.compute();
/*int n = 0;
for (String string : listString) {
//System.out.println("n= " + n);
System.out.println("计算结果:" + string);
//n++;
}*/
}
// 注意:每执行完一批就把这批的计算结果存储到LIST中,是要1000个操作全部完成了才会统一取出结果。
// 而且是多线程同时取出(这里是4个线程,new 线程池时没通过构造函数传递参数设置线程池大小,线程池的线程数默认等于逻辑CPU数)
// ,所以输出的list元素是乱序的
/*for (String string : listString) {
System.out.println("计算结果:" + string);
}*/
}
}
public class ForkJoinPoolTest3 {
public static void main(String[] args) throws Exception {
Future<List<String>> restValue;
ForkJoinPool pool = new ForkJoinPool();
List<String> list2 = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
list2.add("test"+i);
}
// 提交可分解的 PrintTask 任务
pool.submit(new PrintTask3(0, 1000,list2));
//线程阻塞100秒,等待所有任务完成。如果100秒还有任务没执行完成,线程池会关闭,退出任务,
//就会导致部分任务没完成。所以这个线程池阻塞时间必须大于线程池完成所有任务的时间
pool.awaitTermination(100, TimeUnit.SECONDS);
System.out.println("输出完成");
// 关闭线程池
pool.shutdown();
}
}