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