前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >SpringBoot 2.X中的@Async和Java8中的completableFuture的使用比较

SpringBoot 2.X中的@Async和Java8中的completableFuture的使用比较

作者头像
袁新栋-jeff.yuan
发布2020-08-26 09:54:06
2.4K0
发布2020-08-26 09:54:06
举报

背景

看到項目中有使用到Async注解和completetableFuture的runApply方法的使用。兩者都是異步提交方法的方式。那他两都分别在什么场景底下比较适用呢?

  1. 非常的明显的区别,一个是注解一个是方法调用。这样的话带来利好了。注解注释某个方法,那这个方法只要被调用就会产生异步。那使用的completableFuture的话你调用那个方法那个方法才会被异步。
  2. Async 产生的默认使用的线程池是不一样的。一个是forkJoinPool 一个是AsyncTaskExecutor。
  3. 两个都是用默认性能和产生的默认的线程数

@Async简介

为了使得异步可用,Spring提供了一个注解@EnableAsync如果Java的配置文件标注他,那么Spring就会开启同步可用,这样就可以使用注解@Async驱动Spring使用的异步调用,其中的默认线程池也就是AsyncTaskExecutor,默认参数为无限大(首先简单百度了下,网上提到@Async默认异步配置使用的是SimpleAsyncTaskExecutor,该线程池默认来一个任务创建一个线程,在大量的请求的时候,这时就会不断创建大量线程,极有可能压爆服务器内存。如下面的测试情况,无限创建线程) 使用Java配置demo:

package com springboot chapterl3.config
/**** imports ******/
@Configuration
@EnableAsync
public class AsyncConfig implements AsyncConfigurer { 
//定义线程池
Override
public Executor getAsyncExecutor () { 
//定义线程池
ThreadPoolTaskExecutor taskExecutor =new ThreadPoolTaskExecutor(); 
//核心线程数
taskExecutor setCorePool ze (10); 
//线程池最大线程数
taskExecutor setMaxPoolS ze (30) ; 
//线程队列最大线程数
taskExecutor . setQueueCapacity(2000) ; 
//初始化
taskExecutor.initialize(); 
return taskExecutor;
    }
}

CompleteTableTuture简介

点击:https://blog.csdn.net/weixin_40413961/article/details/107703172

两者demo压测比较

使用CompleteTableTuture demo

/**
 * @author yuanxindong
 * @date: 2020/7/31 16:53
 */
@Service
public class AsyncTest {
    @Autowired
    AsycMethodDemo asycMethodDemo;

    @Test
    public void runAsyncTask() throws InterruptedException {
        Thread.sleep(50000);
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        AsycMethodDemo asycMethodDemo = applicationContext.getBean(AsycMethodDemo.class);
        Integer i = 0;
        for (i = 0; i < 100; i++) {
            getTask(asycMethodDemo, i);
        }

        Thread.sleep(1000000);
    }

    private void getTask(AsycMethodDemo asycMethodDemo, Integer i) {
        try {
            CompletableFuture.runAsync(() -> {
                try {
                    asycMethodDemo.asyncMethod(i);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            });
        } catch (Exception e) {

        }
    }

}

运行结果:

在这里插入图片描述
在这里插入图片描述

除了主线程,根据图看到一共起了8个线程。是的forkJoinPool的默认核心线程数是根据CPU的核数来穿建的

  • 使用Java8中的completableFuture的使用demo
/**
 * @author yuanxindong
 * @date: 2020/7/31 16:53
 */
@Service
public class AsyncTest {
    @Autowired
    AsycMethodDemo asycMethodDemo;
    @Test
   public void runAsyncTask() throws InterruptedException {
        Thread.sleep(50000);
        ApplicationContext applicationContext = new AnnotationConfigApplicationContext(MainConfig.class);
        AsycMethodDemo asycMethodDemo =  applicationContext.getBean(AsycMethodDemo.class);
    int i = 0;
    for( i = 0; i< 100;i++){
        asycMethodDemo.asyncMethod(i);
        System.out.println("任务"+i+"执行完成");
    }

    Thread.sleep(1000000);
    }

}

运行结果:

在这里插入图片描述
在这里插入图片描述

可以看出,一共起了100个线程,由于线程起的多可以明显看到这几个任务执行完成的真的很快,这也就是传说中的时间并行执行吧,但是这里会有 一个问题那就是如果任务真的超级多的话,会不会爆掉。

总结

个人感觉Java 8的completeTable比较好用一些,也支持自定义。

  1. Spring的也是OK的,具体情景具体选择吧
  2. @Async的时候一定要设置线程数,以防万一OOM
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-08-03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 背景
  • @Async简介
  • CompleteTableTuture简介
  • 两者demo压测比较
  • 总结
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档