由于需要在for循环中,每条记录都要根据不同的条件,查询出想要的数据。
只在一个线程中查询数据,显然太慢。
那么,为何不能改成多线程调用?
第二次优化,查询数据库由单线程 改成多线程。
但由于该接口是要将查询出的所有数据,都返回回去的,所以要获取查询结果。
使用多线程调用,并且要获取返回值,这种场景使用java8中的CompleteFuture非常合适。
代码调整为:
CompletableFuture[] futureArray = dataList.stream()
     .map(data -> CompletableFuture
          .supplyAsync(() -> query(data), asyncExecutor)
          .whenComplete((result, th) -> {
       })).toArray(CompletableFuture[]::new);
CompletableFuture.allOf(futureArray).join();CompleteFuture 的本质是创建线程 执行,为了避免产生太多的线程,所以使用线程池是非常有必要的。
优先推荐使用ThreadPoolExecutor类,我们自定义线程池。
具体代码如下:
ExecutorService threadPool = new ThreadPoolExecutor(
    8, //corePoolSize线程池中核心线程数
    10, //maximumPoolSize 线程池中最大线程数
    60, //线程池中线程的最大空闲时间,超过这个时间空闲线程将被回收
    TimeUnit.SECONDS,//时间单位
    new ArrayBlockingQueue(500), //队列
    new ThreadPoolExecutor.CallerRunsPolicy()); //拒绝策略也可以使用ThreadPoolTaskExecutor类创建线程池:
@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;
    }
}
