很早之前写异步任务,可能就是直接使用Thread类来操作,例如:
new Thread() { @Override public void run() { // 要执行的异步操作 } }.start(); // 或者这样: new Thread(() -> { // 要执行的异步操作 }).start();
后来慢慢改进成:java.util.concurrent.Executor
在SpringBoot下,可以更加优雅的实现这些操作
首先开启异步的配置,只要增加@EnableAsync注解就可以了
@EnableAsync @SpringBootApplication public class MyApplication { public static void main(String[] args) { SpringApplication.run(MyApplication.class, args); } }
调用示例,给需要异步的方法,加上@Async注解,返回值只能是void或者Future,可以带参数,如下:
@Component public class AsyncDemo { private static final Logger log = LoggerFactory.getLogger(AsyncDemo.class); /** * 最简单的异步调用,返回值为void */ @Async public void asyncInvokeSimplest() { log.info("asyncSimplest"); } /** * 带参数的异步调用 异步方法可以传入参数 * * @param s */ @Async public void asyncInvokeWithParameter(String s) { log.info("asyncInvokeWithParameter, parementer={}", s); } /** * 异常调用返回Future * * @param i * @return */ @Async public Future<String> asyncInvokeReturnFuture(int i) { log.info("asyncInvokeReturnFuture, parementer={}", i); Future<String> future; try { Thread.sleep(1000 * 1); future = new AsyncResult<String>("success:" + i); } catch (InterruptedException e) { future = new AsyncResult<String>("error"); } return future; } }
这样调用没问题:
asyncDemo.asyncInvokeSimplest(); asyncDemo.asyncInvokeWithException("test"); Future<String> future = asyncDemo.asyncInvokeReturnFuture(100); System.out.println(future.get());
注意事项
在相同的类中调用本类中的异步的方法,异步效果会失效
@Component public class AsyncDemo { private static final Logger log = LoggerFactory.getLogger(AsyncDemo.class); /** * 最简单的异步调用,返回值为void */ @Async public void asyncInvokeSimplest() { log.info("asyncSimplest"); } // 反例,在test中,直接调用本类中的asyncInvokeSimplest方法,其实不会异步调用的 public void test() { this.asyncInvokeSimplest(); } }
如果一定在本方法中调用,解决办法如下:
利用ApplicationContext.getBean得到本类的Proxy,然后来调用
@Service public class AsyncDemo { private static final Logger log = LoggerFactory.getLogger(AsyncDemo.class); @Autowired private ApplicationContext applicationContext; private AsyncDemo getSpringProxy() { return applicationContext.getBean(this.getClass()); } /** * 最简单的异步调用,返回值为void */ @Async public void asyncInvokeSimplest() { log.info("asyncSimplest"); } // 本类中调用异步方法不生效的解决办法 public void test() { getSpringProxy().asyncInvokeSimplest(); // 不要这样调用: this.asyncInvokeSimplest(); } }
文章评论