由于需要在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;
}
}