Open v5tech opened 5 years ago
AsyncTaskService 模拟后台耗时请求业务
import org.joda.time.LocalDateTime; import org.springframework.stereotype.Service; import java.util.UUID; import java.util.concurrent.TimeUnit; @Service public class AsyncTaskService { public String uuid() { try { TimeUnit.MILLISECONDS.sleep(5000); System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->工作线程(" + Thread.currentThread().getName() + ")"); } catch (InterruptedException e) { e.printStackTrace(); } return UUID.randomUUID().toString(); } }
AsyncController 异步请求几种写法
import org.joda.time.LocalDateTime; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.core.task.SimpleAsyncTaskExecutor; import org.springframework.scheduling.annotation.EnableAsync; import org.springframework.util.concurrent.ListenableFuture; import org.springframework.util.concurrent.ListenableFutureTask; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RestController; import org.springframework.web.context.request.async.DeferredResult; import org.springframework.web.context.request.async.WebAsyncTask; import java.util.concurrent.Callable; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; /** * 异步Controller */ @RestController @EnableAsync public class AsyncController { @Autowired private AsyncTaskService asyncTaskService; /** * 阻塞请求 * @return */ @GetMapping("blockingRequest") public String blockingRequest() { System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程开始"); String uuid = asyncTaskService.uuid(); System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程结束"); return uuid; } /** * 使用Callable * @return */ @GetMapping("callable") public Callable<String> callable() { System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程开始"); Callable<String> callable = () -> { String uuid = asyncTaskService.uuid(); System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->子任务线程("+Thread.currentThread().getName()+")"); return uuid; }; System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程结束"); return callable; } /** * 使用CompletableFuture * * 使用该方式时,切记自己创建执行器,不要使用内置的 ForkJoinPool线程池,会有性能问题 * * @return */ @GetMapping("completableFuture") public CompletableFuture<String> completableFuture() { ExecutorService executor = Executors.newCachedThreadPool(); System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程开始"); CompletableFuture<String> completableFuture = CompletableFuture.supplyAsync(asyncTaskService::uuid,executor); System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程结束"); return completableFuture; } /** * 使用ListenableFuture * * 使用该方式时,切记自己创建执行器,不要使用内置的 ForkJoinPool线程池,会有性能问题 * * @return */ @GetMapping("listenableFuture") public ListenableFuture<String> listenableFuture() { System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程开始"); ListenableFutureTask<String> listenableFuture = new ListenableFutureTask<>(()-> asyncTaskService.uuid()); Executors.newCachedThreadPool().execute(listenableFuture); System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程结束"); return listenableFuture; } /** * 使用WebAsyncTask * @return */ @GetMapping("asynctask") public WebAsyncTask asyncTask() { SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor(); System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程开始"); WebAsyncTask<String> task = new WebAsyncTask(10000L, executor, ()-> asyncTaskService.uuid()); task.onCompletion(()->{ System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->调用完成"); }); task.onTimeout(()->{ System.out.println("onTimeout"); return "onTimeout"; }); System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程结束"); return task; } /** * 使用DeferredResult * @return */ @GetMapping("deferredResult") public DeferredResult<String> deferredResult() { System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程("+Thread.currentThread().getName()+")开始"); DeferredResult<String> deferredResult = new DeferredResult<>(); CompletableFuture.supplyAsync(()->{ String uuid = asyncTaskService.uuid(); // int abc = 2/0; return uuid; }, Executors.newFixedThreadPool(5)).whenCompleteAsync((result,throwable)->{ if (throwable!=null) { deferredResult.setErrorResult(throwable.getMessage()); }else { deferredResult.setResult(result); } }); // 异步请求超时时调用 deferredResult.onTimeout(()->{ System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->onTimeout"); }); // 异步请求完成后调用 deferredResult.onCompletion(()->{ System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->onCompletion"); }); System.out.println(LocalDateTime.now().toString("yyyy-MM-dd HH:mm:ss:S") + "--->主线程("+Thread.currentThread().getName()+")结束"); return deferredResult; } }
参考文档
https://www.javacodegeeks.com/2015/07/understanding-callable-and-spring-deferredresult.html
https://nickebbitt.github.io/blog/2017/03/22/async-web-service-using-completable-future
AsyncTaskService 模拟后台耗时请求业务
AsyncController 异步请求几种写法
参考文档
https://www.javacodegeeks.com/2015/07/understanding-callable-and-spring-deferredresult.html
https://nickebbitt.github.io/blog/2017/03/22/async-web-service-using-completable-future