众所周知,并行查询可以提高程序运行效率。主线程需要等待所有子线程把数据查询出结果,如果没有设置超时时间,就需要主线程就会一直阻塞到那里,从而占用服务器资源,那么如何设置超时时间呢?
1.在SpringBoot项目中引入线程池
@EnableAsync
@Configuration
public class ThreadPoolsConfig {@Value("${AsyncTaskExecutor.corePooleSize:6}")private Integer corePooleSize;@Value("${AsyncTaskExecutor.maxPoolSize:15}")private Integer maxPoolSize;@Value("${AsyncTaskExecutor.queueCapacity:20000}")private Integer queueCapacity;/*** 自定义线程池*/@Bean("myTaskExecutor")public AsyncTaskExecutor getMyTaskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setThreadNamePrefix("TaskThreadExec--");executor.setCorePoolSize(corePooleSize);executor.setMaxPoolSize(maxPoolSize);executor.setQueueCapacity(queueCapacity);// 放弃等待队列中最旧的任务来添加新的任务executor.setRejectedExecutionHandler(new ThreadPoolExecutor.DiscardOldestPolicy());return executor;}}
2.使用java.util.concurrent.CompletableFuture进行并行查询(未设置超时时间)
CompletableFuture[] asyncList = new CompletableFuture[]{CompletableFuture.runAsync(() -> queryDataA(), asyncTaskExecutor),CompletableFuture.runAsync(() -> queryDataB(), asyncTaskExecutor)};CompletableFuture.allOf(asyncList).join();
3.使用java.util.concurrent.CompletableFuture进行并行查询(设置超时时间)
CompletableFuture[] asyncList = new CompletableFuture[]{CompletableFuture.runAsync(() -> queryDataA(), asyncTaskExecutor),CompletableFuture.runAsync(() -> queryDataB(), asyncTaskExecutor)};try {CompletableFuture.allOf(asyncList).get(3, TimeUnit.SECONDS);} catch (InterruptedException | ExecutionException | TimeoutException e) {System.err.println("多线程查询"+e.getMessage());Thread.currentThread().interrupt();}
需要说明的是,这里的interrupt方法也可以不调用。
interrupt方法的作用如下:
线程A在执行sleep,wait,join时,线程B调用线程A的interrupt方法,的确这一个时候A会有InterruptedException 异常抛出来。
但这其实是在sleep、wait、join这些方法内部会不断检查中断状态的值,而自己抛出的InterruptedException
import java.util.Date;public class MyThread extends Thread{@Overridepublic void run() {while (!isInterrupted()){System.out.println(new Date());}}public static void main(String[] args) throws InterruptedException {MyThread myThread = new MyThread();myThread.start();//1秒后打断子线程Thread.sleep(1000);myThread.interrupt();}
}