首页 > 社交 > 科普中国

从20s优化到500ms,我用了这三招

常驻编辑 科普中国 2022-07-02 节点   线程   批量   接口   性能   评价   组织   业务   数据   系统

由于需要在for循环中,每条记录都要根据不同的条件,查询出想要的数据。Dxl拜客生活常识网

只在一个线程中查询数据,显然太慢。Dxl拜客生活常识网

那么,为何不能改成多线程调用?Dxl拜客生活常识网

第二次优化,查询数据库由单线程 改成多线程。Dxl拜客生活常识网

但由于该接口是要将查询出的所有数据,都返回回去的,所以要获取查询结果。Dxl拜客生活常识网

使用多线程调用,并且要获取返回值,这种场景使用java8中的CompleteFuture非常合适。Dxl拜客生活常识网

代码调整为:Dxl拜客生活常识网

CompletableFuture[] futureArray = dataList.stream()
     .map(data -> CompletableFuture
          .supplyAsync(() -> query(data), asyncExecutor)
          .whenComplete((result, th) -> {
       })).toArray(CompletableFuture[]::new);
CompletableFuture.allOf(futureArray).join();

CompleteFuture 的本质是创建线程 执行,为了避免产生太多的线程,所以使用线程池是非常有必要的。Dxl拜客生活常识网

优先推荐使用ThreadPoolExecutor类,我们自定义线程池。Dxl拜客生活常识网

具体代码如下:Dxl拜客生活常识网

ExecutorService threadPool = new ThreadPoolExecutor(
    8, //corePoolSize线程池中核心线程数
    10, //maximumPoolSize 线程池中最大线程数
    60, //线程池中线程的最大空闲时间,超过这个时间空闲线程将被回收
    TimeUnit.SECONDS,//时间单位
    new ArrayBlockingQueue(500), //队列
    new ThreadPoolExecutor.CallerRunsPolicy()); //拒绝策略

也可以使用ThreadPoolTaskExecutor类创建线程池:Dxl拜客生活常识网

@Configuration
public class ThreadPoolConfig {

    /**
     * 核心线程数量,默认1
     */
    private int corePoolSize = 8;

    /**
     * 最大线程数量,默认Integer.MAX_VALUE;
     */
    private int maxPoolSize = 10;

    /**
     * 空闲线程存活时间
     */
    private int keepAliveSeconds = 60;

    /**
     * 线程阻塞队列容量,默认Integer.MAX_VALUE
     */
    private int queueCapacity = 1;

    /**
     * 是否允许核心线程超时
     */
    private boolean allowCoreThreadTimeOut = false;


    @Bean("asyncExecutor")
    public Executor asyncExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setKeepAliveSeconds(keepAliveSeconds);
        executor.setAllowCoreThreadTimeOut(allowCoreThreadTimeOut);
        // 设置拒绝策略,直接在execute方法的调用线程中运行被拒绝的任务
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 执行初始化
        executor.initialize();
        return executor;
    }
}

相关阅读:

  • ssr链接怎么用(安卓手机ssr怎么添加节点)
  • ssr怎么设置(ssr加速器节点)
  • 节点是什么意思(手机怎么换节点)
  • 「数据结构之字典树Trie」C语言版本实现
  • 网宿科技股份有限公司2021年年度报告摘要300017
  • 《重生之门》热播背后:悬疑剧集寻求差异化,阿里影业自制
  • 互联网后端技术大全!建议收藏
  • A股下半年行情走势的沙盘推演!第一阶段结束时间会是7月
  • 成为国家新基建核心,边缘计算的魅力到底在哪里
  • 牛客网高频算法题系列合并两个排序的链表
    • 网站地图 |
    • 声明:登载此文出于传递更多信息之目的,并不意味着赞同其观点或证实其描述。文章内容仅供参考,不做权威认证,如若验证其真实性,请咨询相关权威专业人士。