SpringBoot-27- @Async实现异步调用 什么是异步调用

SpringBoot-27- @Async实现异步调用

什么是异步调用

异步调用是相对于同步调用的,同步调用是按照顺序进行执行任务,只有上一个任务执行完成下一个任务才能执行,异步调用是指在按照顺序执行任务的过程中不需要等待任务结果的出现,就可以顺序执行下一个任务

异步处理的方式:

  • Java异步处理:Thread/Runnable、Callable/Future

  • Servlet 3.0异步处理: asyncSupported、AsyncContext

  • Spring MVC异步处理: @Async、AsyncTaskExecutor

SpringBoot自身没有对异步调用做很大的变动,基本还是使用SpringMVC的@Async

开启异步调用配置

@EnableAsync
@Configuration
public class MyEnableAsyncConfig {
}

注解:在使用**@EnableWebMvc**注解的时候也可以开启异步调用,但是在SpringBoot中使用异步调用会使得SpringBoot的AutoConfig一部分功能失效。

定义线程池

定义一个或者多个线程池

@EnableAsync
@Configuration
public class MyEnableAsyncConfig {
    @Bean(name = "threadPoolTaskExecutor1")
    public Executor taskExecutor1() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(200);
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("threadPoolTaskExecutor1-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }

    @Bean(name = "threadPoolTaskExecutor2")
    public Executor threadPoolTaskExecutor2() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(10);
        executor.setMaxPoolSize(20);
        executor.setQueueCapacity(200);
        executor.setKeepAliveSeconds(60);
        executor.setThreadNamePrefix("threadPoolTaskExecutor2-");
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        return executor;
    }
}


我们使用ThreadPoolTaskExecutor创建线程池,其参数配置如下:

  • CorePoolSize:设置核心线程数,线程池创建的时候创建线程的个数

  • MaxPoolSize:最大线程数,在换成队列满以后才会申请超过核心线程的线程

  • QueueCapacity:缓冲队列,用来缓冲执行任务的队列

  • KeepAliveSeconds:当超过了核心线程数之外的线程在空闲时间到达之后会被销毁

  • ThreadNamePrefix:线程名称前缀

定义异步调用方法

异步调用方法有两种一个是没有返回值的,一种是有返回值的,具体实现如下:

@Component
public class ComponentTask {

    public static Random random =new Random();

    /**
     * 无返回值
     */
    @Async("threadPoolTaskExecutor2")
    public void asyncMethodWithVoidReturnType_One() throws InterruptedException {
        System.out.println("开始做asyncMethodWithVoidReturnType_One");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(1000));
        long end = System.currentTimeMillis();
        System.out.println("完成asyncMethodWithVoidReturnType_One,耗时:" + (end - start) + "毫秒"+"  threadname:"+Thread.currentThread().getName());


    }
    @Async("threadPoolTaskExecutor1")
    public void asyncMethodWithVoidReturnType_Two() throws InterruptedException {
        System.out.println("开始做asyncMethodWithVoidReturnType_Two");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(2000));
        long end = System.currentTimeMillis();
        System.out.println("完成asyncMethodWithVoidReturnType_Two,耗时:" + (end - start) + "毫秒" +"  threadname:"+Thread.currentThread().getName());

    }
    @Async("threadPoolTaskExecutor1")
    public void asyncMethodWithVoidReturnType_Three() throws InterruptedException {
        System.out.println("开始做asyncMethodWithVoidReturnType_Three");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(3000));
        long end = System.currentTimeMillis();
        System.out.println("完成asyncMethodWithVoidReturnType_Three,耗时:" + (end - start) + "毫秒"+ "  threadname:"+Thread.currentThread().getName());

    }


    /**
     * 有返回值的
     * @return
     */
    @Async("threadPoolTaskExecutor1")
    public Future<String> asyncMethodWithReturnType_One() throws InterruptedException {
        System.out.println("开始asyncMethodWithReturnType_One");
        long start = System.currentTimeMillis();
        Thread.sleep(random.nextInt(10000));
        long end = System.currentTimeMillis();
        System.out.println("完成asyncMethodWithReturnType_One,耗时:" + (end - start) + "毫秒");
        return new AsyncResult<>("任务一完成");
    }
}


在多线程池的时候,我们需要在@Async()指定线程池名称**@Async(“threadPoolTaskExecutor1”)**

单元测试

@SpringBootTest
class SpringBootPart27ApplicationTests {
    @Autowired
    private ComponentTask componentTask;

    @Test
    void contextLoads() throws InterruptedException {
        componentTask.asyncMethodWithVoidReturnType_One();
        componentTask.asyncMethodWithVoidReturnType_Two();
        componentTask.asyncMethodWithVoidReturnType_Three();

        Thread.currentThread().join();

    }

}


在单元测试用例中,注入Task对象,并在测试用例中执行asyncMethodWithVoidReturnType_OneasyncMethodWithVoidReturnType_Two()asyncMethodWithVoidReturnType_Three()三个函数。

执行结果如下:

开始做asyncMethodWithVoidReturnType_One
开始做asyncMethodWithVoidReturnType_Two
开始做asyncMethodWithVoidReturnType_Three
完成asyncMethodWithVoidReturnType_One,耗时:435毫秒  threadname:threadPoolTaskExecutor2-1
完成asyncMethodWithVoidReturnType_Two,耗时:1885毫秒  threadname:threadPoolTaskExecutor1-1
完成asyncMethodWithVoidReturnType_Three,耗时:1904毫秒  threadname:threadPoolTaskExecutor1-2

**

如果您觉得本文不错,欢迎关注,点赞,收藏支持,您的关注是我坚持的动力!

**

原创不易,转载请注明出处,感谢支持!如果本文对您有用,欢迎转发分享!

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值