当前位置: 代码迷 >> 综合 >> Spring线程池ThreadPoolTaskExecutor的简介和使用
  详细解决方案

Spring线程池ThreadPoolTaskExecutor的简介和使用

热度:98   发布时间:2023-10-19 01:45:27.0

一、ThreadPoolTaskExecutor的重要参数

corePoolSize:核心线程数,线程池维护线程的最少数量。
allowCoreThreadTimeOut:是否允许核心线程超时(默认为false)。当为true是,小于等于核心线程数的线程超时会关闭;为false是,小于等于核心线程数的核心线程会一直存活,不管有没有任务。
maxPoolSize:最大线程数量。

keepAliveSeconds:允许空闲时间。如果allowCoreThreadTimeOut为true,则线程空闲时间到达keepAliveSeconds后,该线程会销毁。

queueCapacity:阻塞队列

1.当前线程池中线程数量<corePoolSize,则会新建一个线程执行任务;

2.corePoolSize=<当前线程池中线程数量<maxPoolSize,且阻塞队列还没有满,则将任务放入阻塞队列;

3.corePoolSize=<当前线程池中线程数量<maxPoolSize,且阻塞队列已满,则会新建一个线程执行任务;

4.当前线程池中线程数量>=maxPoolSize,且阻塞队列已满,并且没有空闲的线程执行任务时,有新任务时则会执行拒绝策略;

二、拒绝策略

1.CallerRunsPolicy

如果线程池、队列都满了,添加线程池失败,则主线程会自己去执行任务,不会等待线程池中的线程去执行。

2.AbortPolicy(默认策略)

如果线程池、队列都满了,则丢弃任务,并抛出异常。

3.DiscardPolicy

如果线程池、队列都满了,则丢弃任务,不会抛出异常。

4.DiscardOldestPolicy

如果线程池、队列都满了,则会将最早进入队列的任务删掉,新任务进入队列。

5.自定义策略

如果以上四种策略都不满足业务要求,可以自定义策略。需要实现RejectedExecutionHandler接口,并实现其rejectedExecution方法即可,将具体逻辑写入该方法。

三、合理配置线程池大小

线程池的设置要根据实际需求和使用场景决定,不是配置的越大越好,线程过多会导致内存的高使用量,消耗过多资源。

首先确认CPU核数,然后从线程的应用场景分析是CPU密集型任务,还是IO密集型任务:

1.CPU密集型任务:大部分场景下都是纯CPU计算的任务,比如压缩、解密、算法等一系列消耗CPU资源的任务。一般线程数设置为:CPU核数+1 或者CPU核数*2

2.IO密集型任务:比如文件读写操作、网络通信、数据库操作等任务,不会特别消耗CPU资源,但是IO任务比CPU任务耗时更多,一般线程数设置为:CPU核数*[1+IO耗时/CPU耗时] 或者CPU核数/(1-0.9)

比如CPU核数4,线程池大小设置为40.

四、配合CountDownLatch

CountDownLatch是一个同步计数器,用来协调多个线程之间的同步。

CountDownLatch初始化为线程的数量n,每当一个任务线程执行完之后调用countDownLatch.countDown()方法,计数器数量减1,当计数器数量变为0时,在countDownLatch上await()的线程,也就是等待的主线程就会被唤醒,继续执行主线程的任务。

五、使用

/*** 当前可用CPU数 */
private static final int availabltProcessors = Runtime.getRuntime().availableProcessors();/*** 线程名称*/
private static ThreadFactory threadName = new ThreadFactoryBuilder().setNameFormat("t-%d").build();/*** 线程池配置*/
private static ThreadPoolExecutor executor = new ThreadPoolExecutor(availabltProcessors * 2, availabltProcessors * 5, 200L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>(2000), threadName, new ThreadPoolExecutor.AbortPolicy());public void test() {// 总页数int pageCount = 100;CountDownLatch countDownLatch = new CountDownLatch(pageCount);for (int pageNo = 1; pageNo <= pageCount; pageNo++) {executor.submit(() -> {try {// 分页处理} catch (Exception e) {log.error("分页处理失败...", e);} finally {countDownLatch.countDown();}});}try {countDownLatch.await();} catch (InterruptedException e) {log.error("数据处理失败...", e);}log.info("数据处理完成!");
}

 

 

 

  相关解决方案