本文来源gao.dai.ma.com搞@代*码(网$错误示例,同一个类中使用异步方法:
package com.xqnode.learning.controller; import com.fasterxml.jackson.core.JsonProcessingException; import org.springframework.scheduling.annotation.Async; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.Map; import java.util.concurrent.TimeUnit; @RestController @RequestMapping("/test") public class TestController { @GetMapping("/async") public Map<Object, Object> test() throws InterruptedException, JsonProcessingException { System.out.println("接收到请求。。。"); task(); Map<Object, Object> map = new HashMap<>(); System.out.println("请求结束。。。"); map.put("msg", "操作成功"); map.put("code", "0"); return map; } @Async void task() throws InterruptedException { TimeUnit.SECONDS.sleep(5); System.out.println("线程任务执行结束。。。"); } }
来分析下错误的原因:
当我使用postman调用该接口的时候发现,我预想中的立即返回并没有发生。后来查询资料发现,在controller调用本类中的异步方法,不会生效
正确示例:
package com.xqnode.learning.controller; import com.xqnode.learning.service.AsyncService; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import java.util.HashMap; import java.util.Map; @RestController @RequestMapping("/test") public class TestController { private static final Logger LOG = LoggerFactory.getLogger(TestController.class); @Autowired private AsyncService asyncService; @GetMapping("/async") public Map<Object, Object> test() throws InterruptedException { LOG.info("接收到请求。。。"); asyncService.task(); Map<Object, Object> map = new HashMap<>(); LOG.info("请求结束。。。"); map.put("msg", "操作成功"); map.put("code", "0"); return map; } }
将异步调用放到service中:
package com.xqnode.learning.service; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.scheduling.annotation.Async; import org.springframework.stereotype.Service; import java.util.concurrent.TimeUnit; @Service public class AsyncService { private static final Logger LOG = LoggerFactory.getLogger(AsyncService.class); @Async("asyncExecutor") public void task() throws InterruptedException { TimeUnit.SECONDS.sleep(5); LOG.info("线程任务执行结束。。。"); } }
这时候再重启项目请求该接口,就会发现接口可以立即返回值。而task任务是异步执行的,5秒之后才会打印结果:
补充知识:springboot + @Async 实现异步方法之踩坑填坑
在使用@Async注解实现异步方法的时候,我们项目中实现了AsyncConfigurer接口来自定义线程池和异常处理。其中自定义线程池的代码如上图,异常处理项目中是自定义异常类实现AsyncUncaughtExceptionHandler 接口,这里未贴出代码。那么到底踩了什么坑呢?