Java 不同类型的 ExecutorService invokeAll

Java ExecutorService invokeAll with different types

我正在使用 Java 1.7.

我正在尝试同时执行两种方法。但是,每种方法都有不同的 return 类型。

我有以下内容:

private ExecutorService executorService = Executors.newFixedThreadPool(2);

private void executeConcurrentTasks(final boolean autoBookingEnabled, final TripDTO tripDTO, final ApprovalRequestDetails approvalRequestDetails, final ApprovalRequest approvalRequest, final QuoteResponse quoteResponse, final TripRequirementsResponse tripRequirementsResponse, final List<List<Evaluator>> evaluatorsList, final List<EvaluationApprovalTree> evaluationTree, final Long memberId, final Map<String,Object> properties, final HttpSession session) {

    List<Callable<?>> tasks = Arrays.asList(
        new Callable<BookServicesResponse>() {
            public BookServicesResponse call() throws Exception {
                BookServicesResponse autoBookResponse = bookServices(autoBookingEnabled, tripDTO, approvalRequestDetails, approvalRequest, quoteResponse, memberId, properties, session);
                return autoBookResponse;
            }
        },
        new Callable<ApprovalResponse>() {
            public ApprovalResponse call() throws Exception {
                ApprovalResponse approvalResponse = submitApproval(approvalRequest, tripDTO, tripRequirementsResponse, evaluatorsList, evaluationTree, memberId, properties, session);
                return approvalResponse;
            }
        });

    List<Future<?>> futures = executorService.invokeAll(tasks); // compile error
    
    for (Future<?> future : futures) {
        try {
            Object obj = future.get();
            if (obj instanceof BookServicesResponse) {
                // ...
            } else if (obj instanceof ApprovalResponse) {
                // ...
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

}

编译错误:

问题

是否有一种通用的方法来处理这两种方法的调用,以便 returned 的期货列表每个都有不同的对象?

我不知道这是否是最佳解决方案,它实际上并没有回答如何使用泛型来获得不同可调用对象列表的问题。但我最终使用了两个单独的 Callables 和 Futures。

    Callable<BookServicesResponse> taskBook = new Callable<BookServicesResponse>() {
            public BookServicesResponse call() throws Exception {
                BookServicesResponse autoBookResponse = bookServices(autoBookingEnabled, tripDTO, approvalRequestDetails, approvalRequest, quoteResponse, memberId, properties, session);
                return autoBookResponse;
            }
        };

    Callable<ApprovalResponse> taskApprove = new Callable<ApprovalResponse>() {
            public ApprovalResponse call() throws Exception {
                ApprovalResponse approvalResponse = submitApproval(approvalRequest, tripDTO, tripRequirementsResponse, evaluatorsList, evaluationTree, memberId, properties, session);
                return approvalResponse;
            }
        };

    Future<BookServicesResponse> futureBook = executorService.submit(taskBook);
    Future<ApprovalResponse> futureApprove = executorService.submit(taskApprove);

它无法按照您尝试的方式工作,因为 invokeAll 需要类型为 List<? extends Callable<T>> 而不是 List<? extends Callable<? extends T>> 的参数。您可以认为这是 API.

的缺点

为了解决这个问题,您可以使用 List<Callable<Object>> 或使用 BookServicdsResponseArrovalResponse 的公共超类(我将在此使用 Response例如):

List<Callable<Response>> tasks = Arrays.asList(
        new Callable<Response>() {
            public Response call() throws Exception {
                BookServicesResponse autoBookResponse = bookServices(autoBookingEnabled, tripDTO, approvalRequestDetails, approvalRequest, quoteResponse, memberId, properties, session);
                return autoBookResponse;
            }
        },
        new Callable<Response>() {
            public Response call() throws Exception {
                ApprovalResponse approvalResponse = submitApproval(approvalRequest, tripDTO, tripRequirementsResponse, evaluatorsList, evaluationTree, memberId, properties, session);
                return approvalResponse;
            }
        });

    List<Future<Response>> futures = executorService.invokeAll(tasks); // compile error

您也可以像这样使用“不安全”转换:

List<Future<?>> futures = executorService.invokeAll((List<Callable<Object>>) tasks);

因为您只会从 Callable 中检索元素,所以这不会导致不需要的 ClassCastException