- T 是需要用户定义自己的处理逻辑单元Task,实现 IAsynchronousRender 接口;
- R 是Task 执行完毕后,用户希望获得的结果 Result,实现 IData 接口。
- T 内部要把持着R的成员变量,便于后面执行完毕存储结果
先把使用方法贴上来:
public static void main(String[] args) {
/**
* 任务集合
*/
final List<IAsynchronousRender<R>> independentRenders = new ArrayList<>();
IAsynchronousRender<R> t1 = null;
IAsynchronousRender<R> t2 = null;
IAsynchronousRender<R> t3 = null;
independentRenders.add(t1);
independentRenders.add(t2);
independentRenders.add(t3);
// 创建任务管理器
FusedTaskExcutionManager<IAsynchronousRender<R>, R> excutionManager = new FusedTaskExcutionManager<>();
//将任务集合加入任务队列
excutionManager.addTasks(independentRenders);
//并发渲染
excutionManager.start();
//获取结果
List<R> dataList = independentRenders.stream().map(IData::getData).collect(Collectors.toList());
}
核心类如下:
package com.example.demo.utils.poi.pool;
import com.example.demo.utils.poi.data.IAsynchronousRender;
import org.slf4j.Logger;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @param <T> 任务
* @param <R> 结果
* @author Rain
* 任务执行管理器
*/
public class FusedTaskExcutionManager<T extends IAsynchronousRender<R>,R> {
/**
* 每个管理器,包含 指定个数的线程数
*/
private int ThreadsOfTotal = 15;
private final List<T> taskList = new ArrayList<>();
/**
* 日志
*/
private Logger logger = null;
public FusedTaskExcutionManager() {
}
public FusedTaskExcutionManager(int threadsOfTotal) {
this.ThreadsOfTotal = threadsOfTotal;
}
public FusedTaskExcutionManager(Logger logger) {
this.logger = logger;
}
/**
* 添加任务
*
* @param task
* @return
*/
public FusedTaskExcutionManager<T, R> addTask(T task) {
taskList.add(task);
return this;
}
/**
* 添加多个任务
* @param tasks
* @return
*/
public FusedTaskExcutionManager<T, R> addTasks(Collection<T> tasks) {
taskList.addAll(tasks);
return this;
}
/**
* @ClassName:CompletableFutureDemo
* @Description:多线程并发任务,取结果归集
*/
public void start() {
//计时开始
Long start = System.currentTimeMillis();
//定长10线程池
ExecutorService exs = Executors.newFixedThreadPool(ThreadsOfTotal);
try {
//方式:全流式处理转换成CompletableFuture[]+组装成一个无返回值CompletableFuture,join等待执行完毕。返回结果whenComplete获取
CompletableFuture[] cfs = taskList.stream().map(object -> CompletableFuture.supplyAsync(() -> calc(object), exs).thenApply(h -> h)
//如需获取任务完成先后顺序,此处代码即可
.whenComplete((v, e) -> {
this.log("<----|任务" + v + "完成!result=" + v + ",异常 e=" + e + ",耗时=" + getSeconds(System.currentTimeMillis(), start));
// results.add(v);
})).toArray(CompletableFuture[]::new);
//等待总任务完成,但是封装后无返回值,必须自己whenComplete()获取
CompletableFuture.allOf(cfs).join();
this.log("|<---->|任务完成先后顺序,结果集个数=" + taskList.size() + ",耗时=" + getSeconds(System.currentTimeMillis(), start));
} catch (Exception e) {
e.printStackTrace();
} finally {
exs.shutdown();
}
// return this.results;
}
public static String getSeconds(long endMillis, long startMillis) {
return (endMillis - startMillis) / 1000 + "秒";
}
private R calc(T t) {
R r = null;
try {
//计时开始
long start = System.currentTimeMillis();
//渲染
t.render();
r = t.getData();
//将排序号 记录到 R
// r.setOrdexIndex(t.getOrdexIndex());
this.log("|---->task线程:" + Thread.currentThread().getName() + "任务序号 key=" + t.getKey() + ",完成!+耗时:" + getSeconds(System.currentTimeMillis(), start));
} catch (Exception e) {
e.printStackTrace();
}
return r;
}
private void log(String msg){
// String content = msg;
// System.out.println(msg);
if(this.logger==null){
System.out.println(msg);
}else{
this.logger.info(msg);
}
}
}
/**
* 异步渲染器
* 将 渲染后的数据 无法马上获取,需要通过单独的接口进行获取
* @param <R>
*/
public interface IAsynchronousRender<R> extends IRender<Boolean>, IData<R> , IKeyable<String> {
}
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
/**
* 具备渲染能力,渲染后的数据可以立刻返回
* @param <O> 代表渲染结果
*/
public interface IRender<O>{
O render();
}
/**
* 带有数据特性,具备获取数据能力
* @author Rain
* @param <R> 数据
*/
public interface IData<R> {
R getData();
}
/**
* 逻辑唯一标识 统一接口
* @author Rain
* @param <T>
*/
public interface IKeyable<T> {
T getKey();
}