Future 简介

Java并发专题 带返回结果的批量任务执行 CompletionService ExecutorService.invokeAll

Java程序执行超时——Future接口介绍

异常处理

任务内部异常

  当任务中具体处理方法发生异常,而恰好我们需要获取该方法或者该任务的参数,或对其特殊处理,则可以使用捕获异常的方式构造出参。例如,需要校验一批快递单号是否已经发货,当具体的校验服务抛异常,则可以将这这批待校验的单号作为“未发货”返回,或者标记成其他状态(例:未知)。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
public class MyTask implements Callable<Response> {

private Request request;
private Service service;

@Override
public Response call() {
Response response = null;
try {
//调用方法
response = service.invoke(request);
} catch (Exception e) {
//异常,返回入参
response.setXXX(requese.getXXX());
}
}
}

任务中断异常

  该异常是检查型异常,目的是强制开发者处理这类异常:

1
2
3
4
5
6
7
try {
completionService.take().get();
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}

  由于该场景对所有类型的异常处理均一致,故只捕获 Exception

1
2
3
4
5
try {
future = completionService.take();
taskResult = future.get();
} catch (Exception e) {
}

  任务发生异常,无法返回出参,但是可以获取任务的入参——提交任务前,将任务及其入参存入 Map< Future, TaskRequest>,待发生异常后,方便获取入参,或对其特殊处理,同上。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
TaskRequest taskRequest = new TaskRequest();
// 封装入参 taskRequest
...
Future<Response> future = completionService.submit(taskRequest);
Map<Future<Response>, TaskRequest> futureTaskMap = new HashMap<taskNum>;
// 构建 futureTaskMap

try {
future = completionService.take();
taskResult = future.get();
} catch (Exception e) {
//异常,返回入参
taskRequest = futureTaskMap.get(future);
taskRequest.setXXX(taskRequest.getXXX());
}

  为了优化内存,还可以在任务执行结束或异常之后,将 Map< Future< Response>, TaskRequest> 中的当前元素移除。

1
2
3
4
5
6
7
try {
...
} catch (Exception e) {
...
} finnily {
futureTaskMap.remove(future);
}