主题
面试速答(先看这里)
**一句话结论:**有的时候,我们需要实现这样的功能,比如说我们有多个黑名单需要校验,为了提升效率,需要并发执行,执行过程中,如果有结果先返回了,就判断他是否命中了黑名单,如果命中,则不用再等后续的其他请求了,直接拒绝即可,否则就要等所有的请求都返回,所有的返回都是通过,返回通过。
60秒标准回答:
有的时候,我们需要实现这样的功能,比如说我们有多个黑名单需要校验,为了提升效率,需要并发执行,执行过程中,如果有结果先返回了,就判断他是否命中了黑名单,如果命中,则不用再等后续的其他请求了,直接拒绝即可,否则就要等所有的请求都返回,所有的返回都是通过,返回通过
想要实现这个功能,可以借助 CompletionService
CompletionService是Java8的新增接口,JDK为其提供了一个实现类ExecutorCompletionService。这个类是为线程池中Task的执行结果服务的,即为Executor中Task返回Future而服务的
**答题顺序:**结论 → 原理/机制 → 关键流程 → 场景与取舍 → 易错点
回答主线:
- **要点1:**想要实现这个功能,可以借助 CompletionService 。
- **要点2:**CompletionService是Java8的新增接口,JDK为其提供了一个实现类ExecutorCompletionService。
- **要点3:**CompletionService的实现目标是任务先完成可优先获取到,即结果按照完成先后顺序排序。
**记忆锚点:**CompletionService → Task → Executor → 并发调三个方法 → 这个类是为线程 → Future
加分表达:
- 有的时候,我们需要实现这样的功能,比如说我们有多个黑名单需要校验,为了提升效率,需要并发执行,执行过程中,如果有结果先返回了,就判断他是否命中了黑名单,如果命中,则不用再等后续的其他请求了,直接拒绝即可,否则就要等所有的请求都返回,所有的返回都是通过,返回通过。
追问准备:
- 围绕「CompletionService」:底层原理是什么?使用时有哪些边界和常见坑?
- 围绕「Task」:底层原理是什么?使用时有哪些边界和常见坑?
- 围绕「Executor」:底层原理是什么?使用时有哪些边界和常见坑?
- 如果线上出现异常,你会如何定位、验证并规避?
典型回答
有的时候,我们需要实现这样的功能,比如说我们有多个黑名单需要校验,为了提升效率,需要并发执行,执行过程中,如果有结果先返回了,就判断他是否命中了黑名单,如果命中,则不用再等后续的其他请求了,直接拒绝即可,否则就要等所有的请求都返回,所有的返回都是通过,返回通过。
想要实现这个功能,可以借助CompletionService。
CompletionService是Java8的新增接口,JDK为其提供了一个实现类ExecutorCompletionService。这个类是为线程池中Task的执行结果服务的,即为Executor中Task返回Future而服务的。
CompletionService的实现目标是任务先完成可优先获取到,即结果按照完成先后顺序排序。

主要的代码实现如下:
yaml
//先创建一个线程池
ScheduledExecutorService blackListCheckExecutorService = new ScheduledThreadPoolExecutor(20,
new BasicThreadFactory.Builder().namingPattern("multi-black-list-decision-%d").build());
//定义一个CompletionService,返回值为boolean类型
CompletionService<Boolean> completionService = new ExecutorCompletionService<>(blackListCheckExecutorService);
//把要执行的任务提交给completionService
for (String blackListName : multiBlackListDecisionObject.getBlackListNames()) {
completionService.submit(() -> getData(new BlackListDecisionObject(multiBlackListDecisionObject, blackListName)) != null);
}
try {
int tasks = multiBlackListDecisionObject.getBlackListNames().size();
//再循环中不断尝试get返回结构
while (tasks > 0) {
Future<Boolean> future = completionService.take();
boolean result = future.get();
//拿到一个结果后就判断是否为true
//只要有一个为true直接返回true
if (result) {
return true;
}
tasks--;
}
//都执行完之后,没有true,则最终返回一次false
return false;
} catch (InterruptedException | ExecutionException e) {
return false;
}