第一次使用,也采了好多坑,这里记录下。
在方法上加上@Async注解,不起作用时检查下面几点:
-
调用者和@Async注解使用的方法在一个类中时候不起作用,原因是这个注解需要经过代理对象进行调用才有效(我的解决办法:分开放在不同的类中)。
-
在启动类上开启注解,也就是在启动类xxxApplication.java 上加上注解@EnableAsync
-
-
使用@Async注解的方法归结为两种:没有返回值,有返回值(返回值类型必须是
Future<xxxx>
类型,return new AsyncResult<>(xxxx);)
1、无返回值
比较简单,在方法上加上和@Async注解即可,有线程池方法的在后面括号中写上线程池方法名(@Async(“myAsync”)),不要忘了在启动类上加上注解@EnableAsync。
下面是一个练习小Demo
/**
* 任务类:没有配置线程池
*/
@Component
@Slf4j
public class TaskDemo {
@Async
public void test1() {
String name = Thread.currentThread().getName();
log.info("线程名称:" + name);
try {
// 模拟一系列数据操作,耗时1500
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Async
public void test2() {
String name = Thread.currentThread().getName();
log.info("线程名称:" + name);
try {
// 模拟一系列数据操作,耗时200
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Async
public void test3() {
String name = Thread.currentThread().getName();
log.info("线程名称:" + name);
try {
// 模拟一系列数据操作,耗时400
Thread.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Async
public void test4() {
String name = Thread.currentThread().getName();
log.info("线程名称:" + name);
try {
// 模拟一系列数据操作,耗时900
Thread.sleep(900);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Async
public void test5() {
String name = Thread.currentThread().getName();
log.info("线程名称:" + name);
try {
// 模拟一系列数据操作,耗时1000
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
其他类中调用
private TaskDemo taskDemo;
@GetMapping("/get")
public void get() {
log.info("开始");
long begin = System.currentTimeMillis();
try {
taskDemo.test1();
taskDemo.test2();
taskDemo.test3();
taskDemo.test4();
taskDemo.test5();
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
log.info("任务完成:耗时{}", System.currentTimeMillis() - begin);
}
@Autowired
public void setTaskDemo(TaskDemo taskDemo) {
this.taskDemo = taskDemo;
}
结果:任务完成:耗时1519
2、有返回值
注意:如果有返回值时候,返回值一定是Future<xxx>
/**
* 任务类:没有配置线程池
*/
@Component
@Slf4j
public class TaskDemo {
@Async
public Future<Integer> test1() {
String name = Thread.currentThread().getName();
log.info("线程名称:" + name);
try {
// 模拟一系列数据操作,耗时1500
Thread.sleep(1500);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new AsyncResult<>(1500);
}
@Async
public Future<Integer> test2() {
String name = Thread.currentThread().getName();
log.info("线程名称:" + name);
try {
// 模拟一系列数据操作,耗时200
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new AsyncResult<>(200);
}
@Async
public Future<Integer> test3() {
String name = Thread.currentThread().getName();
log.info("线程名称:" + name);
try {
// 模拟一系列数据操作,耗时400
Thread.sleep(400);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new AsyncResult<>(400);
}
@Async
public Future<Integer> test4() {
String name = Thread.currentThread().getName();
log.info("线程名称:" + name);
try {
// 模拟一系列数据操作,耗时900
Thread.sleep(900);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new AsyncResult<>(900);
}
@Async
public Future<Integer> test5() {
String name = Thread.currentThread().getName();
log.info("线程名称:" + name);
try {
// 模拟一系列数据操作,耗时1000
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
return new AsyncResult<>(1000);
}
}
调用类
private TaskDemo taskDemo;
@GetMapping("/get")
public void get() {
log.info("开始");
long begin = System.currentTimeMillis();
try {
Future<Integer> test1 = taskDemo.test1();
Future<Integer> test2 = taskDemo.test2();
Future<Integer> test3 = taskDemo.test3();
Future<Integer> test4 = taskDemo.test4();
Future<Integer> test5 = taskDemo.test5();
Integer integer1 = 0;
Integer integer2 = 0;
Integer integer3 = 0;
Integer integer4 = 0;
Integer integer5 = 0;
// 等待其他线程执行完毕,任务没有执行结束就一直等待,可以设置get的超时时间
// test1.get(60, TimeUnit.SECONDS); // 设置超时时间,时间单位是秒
// .isDone() 是判断线程执行完毕的标志,执行完毕返回true
while (true){
boolean done1 = test1.isDone();
boolean done2 = test1.isDone();
boolean done3 = test1.isDone();
boolean done4 = test1.isDone();
boolean done5 = test1.isDone();
boolean b = done1 & done2 & done3 & done4 & done5;
if (b){
// .get()方法获取线程执行结果,具有阻塞状态,所以需要死循环进行判断
integer1 = test1.get();
integer2 = test2.get();
integer3 = test3.get();
integer4 = test4.get();
integer5 = test5.get();
break;
}
}
int i = integer1 + integer2 + integer3 + integer4 + integer5;
log.info(i + "$");// 执行结果
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}
log.info("统计完成:耗时{}", System.currentTimeMillis() - begin);
}
@Autowired
public void setTaskDemo(TaskDemo taskDemo) {
this.taskDemo = taskDemo;
}
结果:
没有使用多线程之前执行的结果:
可以看到,执行时间减少了很多!欢迎留言讨论哦!