1 创建合适的线程池:
创建线程池方式参考:https://blog.csdn.net/l123lgx/article/details/105731660
本文创建固定线程个数的线程池:
ExecutorService executorService = Executors.newFixedThreadPool(2);
2 包装ExecutorCompletionService:
ExecutorCompletionService<Map<String, Object>> completionService = new ExecutorCompletionService<>(executorService);
3 线程执行业务:
completionService.submit(() -> {
return methodA();
});
completionService.submit(() -> {
return methodB();
});
private static Map<String, Object> methodB() {
Map<String, Object> mapData = new HashMap<>(3);
Object data = null;
/**
* 业务处理-- 耗时3秒
* data = xxx;
*/
// 返回结果
mapData.put("type", "methodBResult");
mapData.put("data", data);
return mapData;
}
private static Map<String, Object> methodA() {
Map<String, Object> mapData = new HashMap<>(3);
Object data = null;
/**
* 业务处理-- 耗时6秒
* data = xxx;
*/
// 返回结果
mapData.put("type", "methodAResult");
mapData.put("data", data);
return mapData;
}
4 阻塞获取执行结果:
for (int i = 0; i < 2; i++) {
// 获得结果并处理
Map<String, Object> oneMapResult = completionService.take().get();
if ("methodAResult".equalsIgnoreCase(oneMapResult.get("type").toString())) {
// 方法A 返回的结果
}
if ("methodBResult".equalsIgnoreCase(oneMapResult.get("type").toString())) {
// 方法B 返回的结果
}
}
5 完整代码:
package org.lgx.bluegrass.bluegrasscoree.util.testfuture;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorCompletionService;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* @Description TODO
* @Date 2022/9/28 16:42
* @Author lgx
* @Version 1.0
*/
public class CompletionFuture {
public static void main(String[] args) throws InterruptedException, ExecutionException {
ExecutorService executorService = Executors.newFixedThreadPool(2);
ExecutorCompletionService<Map<String, Object>> completionService = new ExecutorCompletionService<>(executorService);
completionService.submit(() -> {
return methodA();
});
completionService.submit(() -> {
return methodB();
});
for (int i = 0; i < 2; i++) {
// 获得结果并处理
Map<String, Object> oneMapResult = completionService.take().get();
if ("methodAResult".equalsIgnoreCase(oneMapResult.get("type").toString())) {
// 方法A 返回的结果
}
if ("methodBResult".equalsIgnoreCase(oneMapResult.get("type").toString())) {
// 方法B 返回的结果
}
}
executorService.shutdown();
}
private static Map<String, Object> methodB() {
Map<String, Object> mapData = new HashMap<>(3);
Object data = null;
/**
* 业务处理
* data = xxx;
*/
// 返回结果
mapData.put("type", "methodBResult");
mapData.put("data", data);
return mapData;
}
private static Map<String, Object> methodA() {
Map<String, Object> mapData = new HashMap<>(3);
Object data = null;
/**
* 业务处理
* data = xxx;
*/
// 返回结果
mapData.put("type", "methodAResult");
mapData.put("data", data);
return mapData;
}
}
6 与Future获取线程执行结果对比:
(1)ExecutorCompletionService,线程在返回结果后会加入到BlockingQueue队列中,所以其可以优先获取耗时最小的线程结果;Future 在获取线程的结果时只能按顺序获取线程的结果;
(2)ExecutorCompletionService ,由于使用了队列进行了Future的结果存储,所以需要手动的调用 take、poll 方法从队列中剔除Future的结果,以此来减小队列的大小,避免OOM;