一、在新创建一个SpringBoot工程中实现基本的网页请求
需要的包和类
- service包:接口AsyncService ,impl包用存放实现类AsyncServiceImpl
- controller包:控制器AsyncController
public interface AsyncService {
boolean tack1() throws InterruptedException;
boolean tack2() throws InterruptedException;
boolean tack3() throws InterruptedException;
}
//注入spring容器表示是一个Service服务处
@Service
public class AsyncServiceImpl implements AsyncService {
@Override
public boolean tack1() throws InterruptedException {
//计算开始时间
long start = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"]task1开始于"+start+"秒");
//让线程暂停1000毫秒=1秒
Thread.sleep(1000);
//计算结束时间
long end = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"]task1结束于"+(end-start)+"秒");
return true;
}
@Override
public boolean tack2() throws InterruptedException {
//计算开始时间
long start = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"]task2开始于"+start+"秒");
//让线程暂停1000毫秒=1秒
Thread.sleep(1000);
//计算结束时间
long end = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"]task2结束于"+(end-start)+"秒");
return true;
}
@Override
public boolean tack3() throws InterruptedException {
//计算开始时间
long start = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"]task3开始于"+start+"秒");
//让线程暂停1000毫秒=1秒
Thread.sleep(1000);
//计算结束时间
long end = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"]task3结束于"+(end-start)+"秒");
return true;
}
}
//组合注解,主要表示为控制层
@RestController
@RequestMapping("/async")
public class AsyncController {
@Autowired
private AsyncService asyncService;
@GetMapping
public String showAsync() throws InterruptedException {
long start = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"]main开始于"+start+"秒");
asyncService.tack1();
asyncService.tack2();
asyncService.tack3();
long end = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"]main结束于"+(end-start)+"秒");
return "success";
}
}
开启springboot的主方法,在网页输入localhost:8080/async。页面上显示success表示请求成功。
如下图所示,还没看出子线程时,运行的任务都是同一条线程在执行,每一个任务运行时间1秒,一共3秒。如果要是开启3个异步子线程的话,那是否总运行时间就为1秒呢?
二、开启异步子线程
在springboot主方法中添加@EnableAsync开启异步任务
//开启异步任务
@EnableAsync
@SpringBootApplication
public class AsycApplication {
public static void main(String[] args) {
SpringApplication.run(AsycApplication.class, args);
}
}
开启子线程后方法返回的对象类型发送了变化,修改之前的接口和实现类
public interface AsyncService {
Future<Boolean> tack1() throws InterruptedException;
Future<Boolean> tack2() throws InterruptedException;
Future<Boolean> tack3() throws InterruptedException;
}
@Service
public class AsyncServiceImpl implements AsyncService {
@Async
@Override
public Future<Boolean> tack1() throws InterruptedException {
//计算开始时间
long start = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"]task1开始于"+start+"秒");
//让线程暂停1000毫秒=1秒
Thread.sleep(1000);
//计算结束时间
long end = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"]task1结束于"+(end-start)+"秒");
return new AsyncResult<>(true);
}
@Async
@Override
public Future<Boolean> tack2() throws InterruptedException {
//计算开始时间
long start = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"]task2开始于"+start+"秒");
//让线程暂停1000毫秒=1秒
Thread.sleep(1000);
//计算结束时间
long end = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"]task2结束于"+(end-start)+"秒");
return new AsyncResult<>(true);
}
@Async
@Override
public Future<Boolean> tack3() throws InterruptedException {
//计算开始时间
long start = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"]task3开始于"+start+"秒");
//让线程暂停1000毫秒=1秒
Thread.sleep(1000);
//计算结束时间
long end = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"]task3结束于"+(end-start)+"秒");
return new AsyncResult<>(true);
}
}
重新发出请求,如下图所示。因为多线程的出场顺序是不可控的,现在可以看出开启异步子线程后每个任务运行的线程的名都是不同的,而且完成了一秒做了3个任务。
在目前中如果要在主线程获取子线程的数据必须所有子线程完成时才能获取。
@RestController
@RequestMapping("/async")
public class AsyncController {
@Autowired
private AsyncService asyncService;
@GetMapping
public String showAsync() throws InterruptedException, ExecutionException {
long start = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"]main开始于"+start+"秒");
Future<Boolean> result1=asyncService.tack1();
Future<Boolean> result2=asyncService.tack2();
Future<Boolean> result3=asyncService.tack3();
/*
*在主线程 获取 子线程的数据
* 必须所有的子线程运行完成
*/
while (!result1.isDone() || !result2.isDone() || !result3.isDone()) {
if (result1.isDone() && result2.isDone() && result3.isDone()) {
break;
}
}
long end = System.currentTimeMillis();
System.out.println(Thread.currentThread().getName()+"]main结束于"+(end-start)+"秒");
return "success " + result1.get()+" "+result2.get()+" "+result3.get();
}
}
再次发出请求,主线程从子线程中获取到了数据
理论上只要电脑的CPU足够强就可以开启无限的子线程,当然不是子线程开得越多,执行的效率就越高。
老板有时认为一个程序员开发一个业务需要10个月,如果10个程序员开发业务就只需要1个月。这时可以说一个孕妇生产需要10个月,那么10个孕妇是不是就可以1个月就可以生孩子了。随便调侃一句😂