Java7环境下Callable与Future未实现异步执行问题求助
问题原因
你代码同步执行的核心问题是调用了Future.get()方法:
Future.get()是阻塞方法,调用后会一直挂起当前线程,直到异步任务执行完成、返回结果或者抛出异常才会继续往下执行。- 你在提交任务后立刻调用了
futureBookAndApprove.get(),等于主线程会一直等异步任务执行完executeBookingAndApproval方法,才会退出executeBookingAndApprovalConcurrently方法,执行后面的日志打印逻辑,所以日志顺序和预期相反。
解决方案
要实现非阻塞的异步执行,你不需要在提交任务后立刻调用get()方法,同时把异步任务的异常捕获逻辑挪到Callable内部即可,修改后的代码如下:
private void executeBookingAndApprovalConcurrently(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) { Callable<Void> taskBookAndApprove = new Callable<Void>() { public Void call() { try { executeBookingAndApproval(autoBookingEnabled, tripDTO, approvalRequestDetails, approvalRequest, quoteResponse, tripRequirementsResponse, evaluatorsList, evaluationTree, memberId, properties, session); } catch (Exception e) { logger.log(Level.SEVERE, "Error calling executeBookingAndApproval in a new thread.", e); } return null; } }; // 仅提交任务到线程池,不阻塞等待执行结果,提交后直接返回 executorService.submit(taskBookAndApprove); }
补充说明
- 如果你后续确实需要获取异步任务的执行结果,可以把
Future对象作为返回值返回,等到主流程所有不需要等待异步结果的逻辑都执行完成后,再调用get()方法获取结果,避免阻塞主流程。 - 注意
HttpSession不是线程安全的,不建议直接传递到异步线程中使用,建议提前把需要的属性从session中取出,以普通参数的形式传递给异步任务,避免并发安全问题。
内容的提问来源于stack exchange,提问作者Richard
相关产品推荐
相关产品推荐

