【发布时间】:2018-10-08 18:57:51
【问题描述】:
我的项目中有一个要求,用户调用 REST API - POST 操作来执行长时间等待的任务,现在我们不想让用户等待,而是希望立即通知用户说“任务已接受”,并在后台触发另一个线程来执行长任务。
我已经尝试了以下代码,但是当 API 返回其他线程时,不会记录任何消息或执行任何任务。我在这里错过了什么。
@POST
@Path("/longtask")
@Consumes(MediaType.APPLICATION_JSON)
public Response longTask() {
LOGGER.info("longTask started by Thread: "+Thread.currentThread().getName());
executor.submit(
new Runnable() {
@Override
public void run() {
new AsyncService().longTask();
}
});
LOGGER.info("longTask completed by Thread: "+Thread.currentThread().getName());
return Response.ok(new MyResponse<>("Task Accepted")).build();
}
异步服务
public class AsyncService {
/**
*
*/
public void longTask(){
LOGGER.info("AsyncService - longTask() Started: "+Thread.currentThread().getName());
try{
//Tried thenAcceptAsync as well
CompletableFuture.supplyAsync(new MyAsyncSupplier()).thenAccept(new MyAsyncConsumer());
}finally{
LOGGER.info("AsyncService - longTask() Completed: "+Thread.currentThread().getName());
}
}
}
MyAsyncSupplier() 和 MyAsyncConsumer() 是一些调用数据库并执行长时间等待任务的任务。 MyAsyncSupplier() 和 MyAsyncConsumer() 下的记录器不会打印。我仅使用示例 java 项目和 main() 方法尝试了相同的操作,并且发生了同样的情况。主要完成 System.out 的那一刻不会打印。
[744832b5-deed-4043-11-111] [myproject] 2018-10-08 18:19:16,836 [http-nio-8080-exec-31] INFO mypackage.MyResource - longTask started by Thread: http-nio-8080-exec-31
[744832b5-deed-4043-11-111] [myproject] 2018-10-08 18:19:16,836 [http-nio-8080-exec-31] INFO mypackage.MyResource - longTask completed by Thread: http-nio-8080-exec-31
[] [] 2018-10-08 18:19:16,837 [pool-64-thread-1] INFO mypackage.AsyncService - AsyncService - longTask() Started: pool-64-thread-1
[744832b5-deed-4043-11-11] [myproject] 2018-10-08 18:19:16,844 [http-nio-8080-exec-31] DEBUG mypackage.InitializationResponseFilter - Media Type set to : application/json
我怎样才能让这个任务继续?
CompletableFuture.supplyAsync(new MyAsyncSupplier()).thenAccept(new MyAsyncConsumer());
更新 1:
由于 MyAsyncSupplier 和 MyAsyncConsumer 类存在一些对象分配问题,上述代码无法正常工作。我进一步调试了代码并修复了它的工作原理。
更新 2:
实际上不需要执行者提交。
@POST
@Path("/longtask")
@Consumes(MediaType.APPLICATION_JSON)
public Response longTask() {
LOGGER.info("longTask started by Thread: "+Thread.currentThread().getName());
new AsyncService().longTask();
LOGGER.info("longTask completed by Thread: "+Thread.currentThread().getName());
return Response.ok(new MyResponse<>("Task Accepted")).build();
}
【问题讨论】:
-
我有点困惑。您说 /longtask 返回后没有记录任何内容,但在您的日志中,您清楚地看到 AsyncService 在打印完整消息后启动。您还记得在 main 中放置一个等待或循环以使其保持活动状态。一旦 main 完成,JVM 就会被杀死。这就是为什么您的简单 java 项目不起作用的原因。
-
记录器在打印的 CompleableFuture 之前。 MySupplier 和 MyConsumer 的一次未在数据库中记录和执行。如果我添加一个等待,那不会让主线程等待吗?
标签: java multithreading jakarta-ee jersey java-threads