Java Jersey Rest API立即返回,长任务继续
我在我的项目中有一个要求,用户调用RESTAPI-POST操作来执行一个长时间等待的任务,现在我们不想让用户等待,而是要立即通知用户任务已接受,并在后台启动另一个线程来执行长时间任务 我已经尝试了下面的代码,但是当API返回其他线程时,不会记录任何消息或执行任何任务。我错过了什么Java Jersey Rest API立即返回,长任务继续,java,multithreading,jakarta-ee,jersey,java-threads,Java,Multithreading,Jakarta Ee,Jersey,Java Threads,我在我的项目中有一个要求,用户调用RESTAPI-POST操作来执行一个长时间等待的任务,现在我们不想让用户等待,而是要立即通知用户任务已接受,并在后台启动另一个线程来执行长时间任务 我已经尝试了下面的代码,但是当API返回其他线程时,不会记录任何消息或执行任何任务。我错过了什么 @POST @Path("/longtask") @Consumes(MediaType.APPLICATION_JSON) public Response longTask() { LOGGER.info("
@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();
}
MyAsyncSupplier和MyAsyncConsumer是调用DB并执行长等待任务的任务。
未打印MyAsyncSupplier和MyAsyncConsumer下的记录器。我用一个示例java项目和main方法尝试了同样的方法,同样的情况也发生了。主设备完成系统的那一刻。输出不打印
[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();
}
我认为你发布的代码很好,工作正常。也许您对MyAsyncSupplier和MyAsyncSupplier的实现是错误的。这是我的实现,试一试
public class FunFun {
ExecutorService executor = Executors.newFixedThreadPool(2);
public static void main(String[] args) {
FunFun f = new FunFun();
f.longTask();
f.shutdown();
// Scanner scanner = new Scanner(System.in); changed to use shutdown.
// scanner.nextLine();
// System.exit(0);
}
public void shutdown() {
executor.shutdown();
}
public String longTask() {
System.out.println("longTask started by Thread: "+Thread.currentThread().getName());
executor.submit(
new Runnable() {
@Override
public void run() {
new AsyncService().longTask();
}
});
System.out.println("longTask completed by Thread: "+Thread.currentThread().getName());
return "Task Accepted";
}
public class AsyncService {
public void longTask(){
System.out.println("AsyncService - longTask() Started: "+Thread.currentThread().getName());
try{
//Tried thenAcceptAsync as well
CompletableFuture.supplyAsync(new MyAsyncSupplier()). thenAcceptAsync(new MyAsyncConsumer());
}finally{
System.out.println("AsyncService - longTask() Completed: "+Thread.currentThread().getName());
}
}
}
public class MyAsyncSupplier implements Supplier<String>{
@Override
public String get() {
System.out.println("Supplying Food");
return "Food";
}
}
public class MyAsyncConsumer implements Consumer<String>{
@Override
public void accept(String t) {
System.out.println("Nom Nom " + t);
}
}
}
我有点困惑。您说/longstask返回后没有记录任何内容,但在您的日志中可以清楚地看到,在打印完完整消息后,AsyncService将启动。你还记得在主电路中设置一个等待或循环来保持它的活力吗。一旦完成main,JVM就会被杀死。这就是为什么你的简单java项目不起作用的原因。日志记录者在打印出完整的未来之前。MySupplier和MyConsumer提供的once不会记录在数据库中并执行。如果我加上等待,这难道不会让主线等待吗?如果你投了反对票,至少告诉我为什么,这样我可以从中吸取教训。查尔斯,我不知道谁/为什么投了反对票。但是我觉得不需要扫描器和System.exit0代码。在这种情况下,因为你有一个执行器,如果你没有System.exit0,它将保持程序运行;更好的解决办法是关闭执行器。还注意到thenAccept未使用ThenAcceptSync。您是对的,longTask不需要执行器,但您可以在SupplySync和AccpetAsync调用中使用它,这将为您提供更多的控制。此外,如果你觉得这篇文章有帮助,你可以投票,甚至接受答案。没有压力,但我喜欢rep:
public class FunFun {
ExecutorService executor = Executors.newFixedThreadPool(2);
public static void main(String[] args) {
FunFun f = new FunFun();
f.longTask();
f.shutdown();
// Scanner scanner = new Scanner(System.in); changed to use shutdown.
// scanner.nextLine();
// System.exit(0);
}
public void shutdown() {
executor.shutdown();
}
public String longTask() {
System.out.println("longTask started by Thread: "+Thread.currentThread().getName());
executor.submit(
new Runnable() {
@Override
public void run() {
new AsyncService().longTask();
}
});
System.out.println("longTask completed by Thread: "+Thread.currentThread().getName());
return "Task Accepted";
}
public class AsyncService {
public void longTask(){
System.out.println("AsyncService - longTask() Started: "+Thread.currentThread().getName());
try{
//Tried thenAcceptAsync as well
CompletableFuture.supplyAsync(new MyAsyncSupplier()). thenAcceptAsync(new MyAsyncConsumer());
}finally{
System.out.println("AsyncService - longTask() Completed: "+Thread.currentThread().getName());
}
}
}
public class MyAsyncSupplier implements Supplier<String>{
@Override
public String get() {
System.out.println("Supplying Food");
return "Food";
}
}
public class MyAsyncConsumer implements Consumer<String>{
@Override
public void accept(String t) {
System.out.println("Nom Nom " + t);
}
}
}
longTask started by Thread: main
longTask completed by Thread: main
AsyncService - longTask() Started: pool-1-thread-1
Supplying Food
Nom Nom Food
AsyncService - longTask() Completed: pool-1-thread-1