一篇简单实战带你快速上手SpringBoot异步任务

本文通过实例展示了如何在SpringBoot工程中创建网页请求,并开启异步子线程。开启异步任务后,多线程并发执行,提高了任务处理效率。尽管线程数量增多不直接等同于效率提升,但正确使用可以显著改善性能。
摘要由CSDN通过智能技术生成

一、在新创建一个SpringBoot工程中实现基本的网页请求

需要的包和类

  1. service包:接口AsyncService ,impl包用存放实现类AsyncServiceImpl
  2. 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个月就可以生孩子了。随便调侃一句😂

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值