利用future实现并行容器工具
使用场景
在平时的业务功能开发中,我们会遇到因为需要聚合多种下游的原子数据,会发起多次服务的调用链路,如图:
这样的调用链路,上下游的数据没有强依赖关系,但是却是一个串行的请求链路,请求->响应 在 发起请求,如果系统资源允许的话,利用异步线程能力可以降低接口响应耗时,提高用户体验。
线程工具类使用
异步线程执行器
import com.google.common.util.concurrent.ThreadFactoryBuilder;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.Future;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
/**
* 异步任务执行线程池
*/
public final class AsyncTaskExecutor {
/**
* 日志服务
*/
private static final Logger LOGGER = LoggerFactory
.getLogger(AsyncTaskExecutor.class);
/**
*
*/
public static final int CORE_POOL_SIZE = 80;
/**
* 默认最大
*/
public static final int MAX_POOL_SIZE = 400;
/**
* 默认超时毫秒
*/
public int time_out = 3000;
/**
* 默认超时时间单位
*/
public TimeUnit time_out_unit = TimeUnit.MILLISECONDS;
/**
* 线程池
*/
private static final ThreadPoolExecutor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(
CORE_POOL_SIZE,
MAX_POOL_SIZE, 500,
TimeUnit.MILLISECONDS,
new ArrayBlockingQueue(10),new ThreadFactoryBuilder().setNameFormat("async-task-pool-").build());
/**
* future请求队列
*/
private final LinkedBlockingQueue<Future> FUTURE_QUEUE;
/**
* 初始化队列大小
* @param size
*/
public AsyncTaskExecutor(int size) {
FUTURE_QUEUE = new LinkedBlockingQueue<Future>(size);
}
/**
* 设置任务超时时间
* @param time
* @param timeUnit
*/
public void setTimeOut(int time, TimeUnit timeUnit){
this.time_out = time;
this.time_out_unit = timeUnit;
}
/**
* 添加异步任务
* @param function
* @param param
* @param <T>
* @param <R>
* @return
*/
public <T, R> TaskEntry add(Function<T, R> function, T param) {
// 声明一个对象引用
final TaskEntry<R> entry = new TaskEntry<>();
Future<R> future = THREAD_POOL_EXECUTOR.submit(new TracerCallable<R>() {
@Override
public R doCall() throws Exception {
// 执行结果赋值给引用
entry.setE(function.apply(param));
return entry.getE();
}
});
try {
FUTURE_QUEUE.put(future);
} catch (InterruptedException e) {
LogUtil.error(LOGGER, e, "async Task 提交任务");
}
return entry;
}
/**
* 执行任务,同步阻塞
*/
public void executor() {
FUTURE_QUEUE.forEach(e -> {
try {
e.get(time_out, time_out_unit);
} catch (Exception e1) {
LogUtil.error(LOGGER, e1, "执行async Task 任务失败");
}
});
}
/**
* 任务结果对象
* @param <E>
*/
public static class TaskEntry<E> {
/**
* 结果引用
*/
E e;
/**
* Getter method for property <tt>e</tt>.
*
* @return property value of e
*/
public E getE() {
return e;
}
/**
* Setter method for property <tt>e</tt>.
*
* @param e value to be assigned to property e
*/
public void setE(E e) {
this.e = e;
}
}
}
初始任务队列 & 添加任务
// 初始化任务队列数
AsyncTaskExecutor asyncTask = new AsyncTaskExecutor(4);
// 添加任务, entry 就是执行结果的对象引用
AsyncTaskExecutor.TaskEntry<List<A>> entry = asyncTask.add(new Function<String, List<A>>() {
@Override
public List<A> apply(String userId) {
return AManager.query(userId);
}
}, userId);
执行任务
// 执行线程任务, 会阻塞主线程,直到任务超时,或者全部返回结果
asyncTask.executor();