本文转载自微信公众号《六脉神剑的程序人生》,作者六脉神剑小六六。转载本文请联系六脉神剑的程序生活公众号。就在我看项目代码的时候,发现了WebAsyncTask这个新东西。我给大家科普一下。它不是那么深入。不喜勿喷!SpringBoot对同步调用和异步调用采用异步请求处理。除了异步请求,一般我们用的比较多的是异步调用。通常在开发过程中,会遇到与实际业务无关、没有亲近性的方法。比如记录日志信息等服务。这时候就正常起一个新线程做一些业务处理,让主线程异步执行其他业务。同步请求异步请求SprinBoot中@Async异步方法异步的好处是可以提高程序的吞吐量。一个任务允许耗时的异步处理,并继续同步处理后续任务。异步任务可以返回结果。得到结果后,可以结合同步处理过程中的变量一起处理计算。具体在Spring中使用,基于@Async注解的方法称为异步方法;这些方法在执行时会在一个独立的线程中执行,调用者可以继续进行其他操作,无需等待它完成。自定义线程池异步调用配置@EnableAsync使@Async生效@SpringBootApplication@EnableAsyncpublicclassApplication{publicstaticvoidmain(String[]args){SpringApplication.run(Application.class,args);}}自定义线程池@Component@Scope//单例publicclassMyExecutePoll{@BeanpublicExecutormyAsyncPool(){ThreadPoolTask??Executorexecutor=newThreadPoolTask??Executor();//核心线程池大小executor.setCorePoolSize(20);//最大线程数executor.setMaxPoolSize(40);//队列容量executor.setQueueCapacity(50);//活动时间executor.setKeepAliveSeconds(300);//线程名前缀executor.setThreadNamePrefix("MyExecutor-");//线程池关闭时,等待所有任务完成后再继续销毁其他Bean,这样异步线程Destruction优先于Redis等处理报错executor.setWaitForTasksToCompleteOnShutdown(true);//设置任务在线程池中的等待时间,如果过了这个时间还没有被销毁,则强制销毁到确保应用程序可以在最后关闭而不是阻塞执行器.setAwaitTerminationSeconds(60);//setRejectedExecutionHandler:当pool达到maxsize时,如何处理新任务//CallerRunsPolicy:不在新线程中执行任务,但是执行executor.setRejectedExecutionHandler(newThreadPoolExecutor.CallerRunsPolicy());executor.initialize();returnexecutor;}}使用@Async@Async("myAsyncPool")//@Async使用默认线程publicFuturedoTask()throwsException{//业务处理使用Future返回异步调用结果returnnewAsyncResult<>("Taskcompleted");Spring中使用Async注解需要注意的几点:AsyncTest.java,测试类,调用异步任务,同时执行同步方法OrderService.java,异步任务类,提供异步方法AsyncThreadPoolConfig.java,异步任务线程pool配置类,配置异步任务操作的线程池大小基于Spring的异步请求Spring可以通过Callable或者WebAsyncTask实现异步请求。下面我们就来看看这两种实现方式吧!CallableCallable为异步生成返回值提供基本支持。简单的说,一个request进来了,如果你使用Callable,DispatcherServlet和所有的Filters在拿到返回数据之前会退出Servlet容器线程,但是response仍然保持打开状态。一旦返回的数据可用,DispatcherServlet将被再次调用并以异步方式处理。返回一个值给请求者。这样做的好处是请求不会长时间占用服务连接池,提高服务器的吞吐量。@GetMapping("/callable")publicCallabletestCallable()throwsInterruptedException{log.info("主线程启动!");Callableresult=newCallable(){@OverridepublicStringcall()throwsException{log.info("副线程开始!");Thread.sleep(1000);log.info("副线程结束!");return"SUCCESS";}};log.info("主线程结束!");returnresult;}输出结果主线程启动!主线结束!二级线程开始!二次元线程结束!WebAsyncTask对服务的请求由Web容器的线程接收。我们可以使用WebAsyncTask将这个请求分发到一个新的线程Execution中,容器的线程可以接收其他请求的处理。一旦WebAsyncTask返回数据,会再次调用并处理,并以异步的方式将值返回给请求端,但其实我觉得前端请求rt不会缩短。/***Query*/@RequestMapping(method=RequestMethod.GET,value="/aysncTask/{testId}")@ResponseStatus(HttpStatus.OK)publicWebAsyncTaskaysncTask(@PathVariable("testId")StringtestId){System.out.println(String.format("/aysncTask/%s调用threadidis:%s",testId,Thread.currentThread().getName()));Callablecallable=()->{Thread.sleep(1000L);Responseresponse=newResponse(true,"异步执行成功");System.out.println(String.format("/aysncTask/%s调用threadidis:%s",testId,Thread.currentThread().getName()));returnresponse;};returnnewWebAsyncTask(callable);}控制台打印如下:执行业务逻辑之前的线程和具体处理业务逻辑的线程不一样,实现了我们的目标。前缀async-customize-1是我们的习惯。下面会说/aysncTask/12348567676调用threadidis:http-nio-8084-exec-1/aysncTask/12348567676调用threadidis:async-customize-1。事实上,WebAsyncTask比Callable官方的说法是有以下优势。这是给您的屏幕截图:如果我们需要回调来处理超时或错误,我们可以使用WebAsyncTask而不是Callable。在实际使用中,我不推荐直接使用Callable,而是使用Spring提供的WebAsyncTask,它对Callable进行了封装,功能更强大,大家一起研究。