很早之前写异步任务,可能就是直接使用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();
}
}
文章评论