文章目录
1. 最普通的接口类实现@Async
1.1 启动类配置,主要添加:@EnableAsync
1.2 写一个方法和接口实现异步方法
service:
public interface MyAsyncService {
void doTaskOne();
void doTaskTwo();
void doTaskThree();
}
serviceImpl:
package com.pf.org.cms.hcg.system.service.impl;
import com.pf.org.cms.hcg.system.service.MyAsyncService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.Random;
@Service
public class MyAsyncImpl implements MyAsyncService {
public static Random random = new Random();
@Async
@Override
public void doTaskOne() {
System.out.println("开始做任务一");
long start = System.currentTimeMillis();
try {
Thread.sleep(random.nextInt(10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("完成任务一,耗时:" + (end - start) + "毫秒");
}
@Override
@Async
public void doTaskTwo() {
System.out.println("开始做任务二");
long start = System.currentTimeMillis();
try {
Thread.sleep(random.nextInt(10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("完成任务二,耗时:" + (end - start) + "毫秒");
}
@Override
@Async
public void doTaskThree() {
System.out.println("开始做任务三");
long start = System.currentTimeMillis();
try {
Thread.sleep(random.nextInt(10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("完成任务三,耗时:" + (end - start) + "毫秒");
}
}
1.3 controller调用
@GetMapping("/async")
@ResponseBody
public Long async() throws InterruptedException {
long start = System.currentTimeMillis();
Thread.sleep(2000);
myAsyncService.doTaskOne();
myAsyncService.doTaskTwo();
myAsyncService.doTaskThree();
long end = System.currentTimeMillis();
System.out.println("直接返回耗时:" + (end - start));
return (end - start);
}
1.4 结果分析
开始做任务一
开始做任务二
直接返回耗时:2017
开始做任务三
完成任务二,耗时:1125毫秒
完成任务一,耗时:2961毫秒
完成任务三,耗时:3155毫秒
发现其实并不是在三个任务完成之后才进行返回,而是直接返回结果,目的达到
2. 不通过接口的能不能实现@Async功能呢?
我们直接在controller里面写一个方法,并标注他是异步的,看看能不能实现?
2.1 controller实现
@Async
public String send() {
long start = System.currentTimeMillis();
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("第N条.........." + i);
}
long end = System.currentTimeMillis();
return "10条消息发送完成" + "耗时:" + (end - start);
}
@GetMapping("/asyncError")
@ResponseBody
public Long asyncError() throws InterruptedException {
long start = System.currentTimeMillis();
Thread.sleep(2000);
System.out.println(send());
long end = System.currentTimeMillis();
System.out.println("直接返回耗时:" + (end - start));
return (end - start);
}
2.2 分析结果
第N条..........0
第N条..........1
第N条..........2
第N条..........3
第N条..........4
第N条..........5
第N条..........6
第N条..........7
第N条..........8
第N条..........9
10条消息发送完成耗时:10005
直接返回耗时:12005
发现直接在controller里面写一个异步方法并不能满足需求,所以要实现异步,必须方法在一个实体类中,而且不和调用的地方处于同一个类
3. 一个service里面的方法调用其它的异步方法
3.1 修改service方法
service
public interface MyAsyncService {
void doTaskOne();
void doTaskTwo();
void doTaskThree();
void doAllTask();
}
serviceIMPL
package com.pf.org.cms.hcg.system.service.impl;
import com.pf.org.cms.hcg.system.service.MyAsyncService;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.Random;
@Service
public class MyAsyncImpl implements MyAsyncService {
public static Random random = new Random();
@Async
@Override
public void doTaskOne() {
System.out.println("开始做任务一");
long start = System.currentTimeMillis();
try {
Thread.sleep(random.nextInt(10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("完成任务一,耗时:" + (end - start) + "毫秒");
}
@Override
@Async
public void doTaskTwo() {
System.out.println("开始做任务二");
long start = System.currentTimeMillis();
try {
Thread.sleep(random.nextInt(10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("完成任务二,耗时:" + (end - start) + "毫秒");
}
@Override
@Async
public void doTaskThree() {
System.out.println("开始做任务三");
long start = System.currentTimeMillis();
try {
Thread.sleep(random.nextInt(10000));
} catch (InterruptedException e) {
e.printStackTrace();
}
long end = System.currentTimeMillis();
System.out.println("完成任务三,耗时:" + (end - start) + "毫秒");
}
@Override
public void doAllTask() {
System.out.println("这个方法会调用三个异步方法");
long start = System.currentTimeMillis();
doTaskOne();
doTaskTwo();
doTaskThree();
long end = System.currentTimeMillis();
System.out.println("完成三个方法,耗时:" + (end - start) + "毫秒");
}
}
3.2 controller完成调用
@GetMapping("/asyncToOne")
@ResponseBody
public Long asyncToOne() throws InterruptedException {
long start = System.currentTimeMillis();
Thread.sleep(2000);
myAsyncService.doAllTask();
long end = System.currentTimeMillis();
System.out.println("直接返回耗时:" + (end - start));
return (end - start);
}
这个方法会调用三个异步方法
开始做任务一
完成任务一,耗时:2618毫秒
开始做任务二
完成任务二,耗时:5365毫秒
开始做任务三
完成任务三,耗时:7520毫秒
完成三个方法,耗时:15503毫秒
直接返回耗时:17506
发现并没有完成异步,发现这个方法也行不通,那如果在doAllTask()
上加一个异步呢?
4 在调用异步方法的方法上添加异步@Async
@Override
@Async
public void doAllTask() {
System.out.println("这个方法会调用三个异步方法");
long start = System.currentTimeMillis();
doTaskOne();
doTaskTwo();
doTaskThree();
long end = System.currentTimeMillis();
System.out.println("完成三个方法,耗时:" + (end - start) + "毫秒");
}
发现居然成功了,效果如下
直接返回耗时:2013
这个方法会调用三个异步方法
开始做任务一
完成任务一,耗时:8296毫秒
开始做任务二
完成任务二,耗时:9146毫秒
开始做任务三
完成任务三,耗时:5498毫秒
完成三个方法,耗时:22940毫秒
但是要注意的是无论是否添加@Async,System.out.println("完成三个方法,耗时:" + (end - start) + "毫秒");
这个都只会在这个方法的最后执行,也就是三个异步的方法结束后猜会执行,而不是直接返回