springboot中使用异步调用

在日常开发过程中,大多数是基于调用一个方法时,里面业务执行的是同步方式实现,很少用到异步的方式去实现。
同步调用:同步调用指程序按照定义顺序依次执行,每一行程序都必须等待上一行程序执行完成之后才能执行;
异步调用:异步调用指程序在顺序执行时,不等待异步调用的语句返回结果就执行后面的程序。
对比发现异步比同步快很多,节省很多的时间,也会相对提高效率。

、接下来我们测试同步,我们可以通过一个简单的接口调用实现如图
在这里插入图片描述
//测试同步
@RequestMapping(value = “/testSync”)
@ResponseBody
public String testSync()throws InterruptedException {

    System.out.println("当前线程名:"+Thread.currentThread().getName());
    LocalTime time1 = LocalDateTime.now().toLocalTime();
    System.out.println("第一次调用时间:"+ time1);

    Thread.sleep(4000);//此时需要处理一个InterruptedException异常
    LocalTime time2 = LocalDateTime.now().toLocalTime();
    System.out.println("第二次调用时间:"+ time2);

    //得出两个时间差
    Duration duration = Duration.between(time1,time2);
    long timeC = duration.toMillis();
    System.out.println("两者相差:"+ (timeC/1000)+"秒");

    return "666666";
}

在这里插入图片描述
从结果来看,我们可也看到同步是在我们上一个执行完才开始执行的,中间会有个等待的时间,比如我们在记录日志时候就可以通过异步方式来实现,不需要等待。

、我们来试试异步方式调用一个程序的结果,我们使用的是springboot,接下来我们采用两种方式来实现看看,
1.使用@Async和@EnableAsync注解;
(简单介绍一下,spring从3.0版本开始支持异步调用,在方法或者类上一个@Async注解就可以,注意这个类不能是加了@Configuration注解,否则不支持,原因@Configuration注解会对当前类进行代理增强,这个时候返回的类是一个经过代理的类,这个时候的方法可能已经不是原方法了。
在3.1版本的时候加上了@EnableAsync注解,基于@Import注解进行扩展的)
2.通过自定义多线程完成;

**1.**我们自定义多线程
如图所示
在这里插入图片描述

//	测试异步
    @RequestMapping(value = "/testAsync")
    @ResponseBody
    public String testAsync()throws InterruptedException {
    System.out.println("controller当前线程名:"+Thread.currentThread().getName());
    LocalTime time1 = LocalDateTime.now().toLocalTime();
    System.out.println("第一次调用时间:"+ time1);

    Thread thread = new Thread(new TestAsync());
    thread.start();
    //Thread.sleep(4000);//此时需要处理一个InterruptedException异常
    LocalTime time2 = LocalDateTime.now().toLocalTime();
    System.out.println("第二次调用时间:"+ time2);
    //得出两个时间差
    Duration duration = Duration.between(time1,time2);
    long timeC = duration.toMillis();
    System.out.println("1号结果两者相差:"+ (timeC/1000)+"秒");

    return "666666";
}

我们再写一个实现Runnable接口
把从同步方式抽出来方法或者业务放进线程执行体中。
如图
在这里插入图片描述

public class TestAsync implements Runnable {

@Override
public void run() {
    System.out.println("Async当前线程名称:"+Thread.currentThread().getName());
    LocalTime time1 = LocalDateTime.now().toLocalTime();
    System.out.println("第一次调用时间:"+ time1);
    try{
        Thread.sleep(3000);
    }catch (InterruptedException e){
        e.printStackTrace();
    }
    LocalTime time2 = LocalDateTime.now().toLocalTime();
    System.out.println("第二次调用时间:"+ time2);

    //得出两个时间差
    Duration duration = Duration.between(time1,time2);
    long timeC = duration.toMillis();
    System.out.println("2号结果两者时间相差:"+ (timeC/1000)+"秒");
}
}

然后我们启动执行后,可以看到执行结果
在这里插入图片描述
我们可以看到2号结果在最后打印,说明异步处理成功,调用controller中1号结果方法不需要等待2号结果那个方法执行完。

2.我们来使用@Async和@EnableAsync注解进行处理

首先我们新建一个配置类
在这里插入图片描述

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.AsyncConfigurerSupport;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Configuration
@EnableAsync
public class AsyncConfigurer extends AsyncConfigurerSupport {

@Bean
public ThreadPoolTaskExecutor asyncExecutor(){
    ThreadPoolTaskExecutor threadPoolExecutor = new ThreadPoolTaskExecutor();
    // 设置核心线程数
    threadPoolExecutor.setCorePoolSize(3);
    // 设置最大线程数
    threadPoolExecutor.setMaxPoolSize(3);
    // 等待所有任务结束后再关闭线程池
    threadPoolExecutor.setWaitForTasksToCompleteOnShutdown(true);
    threadPoolExecutor.setAwaitTerminationSeconds(60*15);
    return threadPoolExecutor;
}
}

*这个类也试了一下,去掉也能执行。

我们弄个测试方法
在这里插入图片描述

//测试异步 注解方式
@RequestMapping(value = "/testAsyncZhuJie")
@ResponseBody
public String testAsyncZhuJie()throws InterruptedException {

    System.out.println("controller中当前线程名:"+Thread.currentThread().getName());
    LocalTime time1 = LocalDateTime.now().toLocalTime();
    System.out.println("controller中第一次调用时间:"+ time1);
    //业务调用
    asyncService.testAsyncZhuJie();
    Thread.sleep(4000);//此时需要处理一个InterruptedException异常
    LocalTime time2 = LocalDateTime.now().toLocalTime();
    System.out.println("controller中第二次调用时间:"+ time2);
    //得出两个时间差
    Duration duration = Duration.between(time1,time2);
    long timeC = duration.toMillis();
    System.out.println("controller中1号结果两者相差:"+ (timeC/1000)+"秒");

    return "666666";
}

然后在service实现类中写了个方法方便调用
在这里插入图片描述

@Async
@Override
public void testAsyncZhuJie() {
    System.out.println("Service中Async当前线程名称:"+Thread.currentThread().getName());
    LocalTime time1 = LocalDateTime.now().toLocalTime();
    System.out.println("Service中第一次调用时间:"+ time1);
    try{
        Thread.sleep(3000);
    }catch (InterruptedException e){
        e.printStackTrace();
    }
    LocalTime time2 = LocalDateTime.now().toLocalTime();
    System.out.println("Service中第二次调用时间:"+ time2);

    //得出两个时间差
    Duration duration = Duration.between(time1,time2);
    long timeC = duration.toMillis();
    System.out.println("Service中2号结果两者时间相差:"+ (timeC/1000)+"秒");
     }

执行结果如下
在这里插入图片描述
至此我们可以看到,如果service方法在最后打印,说明controller在执行后不需要等待service全部执行完才走,注意这个@Async注解没有会失效,结果就是等service全部执行完了,controller才走接下来的方法。
以上都是个人亲测,也是日常开发过程中所用的方式。如果有什么不对的地方,希望大家指正,谢谢了!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值