并发编程 之 线程池实战&配置建议(二)

本篇围绕线程池在不同场景下的使用,各种参数调优&配置,包括线程池的关闭等;

将结合场景、源码和示例代码来说明其中关键。

目录

1.  创建线程池

      1.1  corePoolSize

      1.2  maximumPoolSize

      1.3  workQueue

        1.3.1 ArrayBlockingQueue

        1.3.2 LinkedBlockingQueue

        1.3.3 SynchronousQueue

      1.4 TimeUnit和keepAliveTime

      1.5  ThreadFactory

      1.6 RejectedExecutionHandler

2. 使用线程池

         2.1 execute()提交任务

         2.2 submit(Runnable) 无返回值

         2.3 submit(Runnable task, T result) 有"返回值"

         2.4 submit(Callable) 真有返回值

3.关闭线程池

       3.1 关闭方法对比

       3.2 何时关闭线程池呢? 

4. 合理配置线程池

       4.1 阻塞队列

       4.2 饱和策略

       4.3 线程数


1.  创建线程池

        之前分析过使用Executors创建线程池的弊端了,它们正是通过new ThreadPoolExecutor(...)

的方式来创建的。其实我们只要通过合理配置该构造函数的参数,就能得到一个稳定可控的池了。

线程池构造函数

        以上就是线程池的全参构造函数,可以看到前面两个 if() 都是参数合法性校验。

      1.1  corePoolSize

         定义了线程池中最少要保持的线程数,即使线程池中没有任务,核心线程也会一直存活,直到线程池被关闭;

        在创建线程池后,可以通过调用  prestartAllCoreThreads()方法提前创建线程等待任务;

        也可以通过设置  allowCoreThreadTimeOut(true)来控制核心线程数是否受超时配置的影响。 

    public void allowCoreThreadTimeOut(boolean value) {
        if (value && keepAliveTime <= 0)
            throw new IllegalArgumentException("Core threads must have nonzero keep alive times");
        if (value != allowCoreThreadTimeOut) {
            allowCoreThreadTimeOut = value;
            if (value)
                interruptIdleWorkers();
        }
    }

      1.2  maximumPoolSize

        允许的最大线程数,如果队列满了,并且已创建的线程数小于最大线程数时新建线程;

        如果使用了无界队列的话这个参数就失效了,这点要特别注意。

      1.3  workQueue

         图中比较多我们只需要关注 java.util.concurrent 包下的几个就可以了。

          1.3.1 ArrayBlockingQueue

             基于数组结构四号线的有界阻塞队列,按照FIFO原则进行排序;内部通过ReentrantLock实现线程安全,可以通过构造方法参数fair 实现公平锁。

        1.3.2 LinkedBlockingQueue

        基于链表结构实现的阻塞队列,按照FIFO原则排序,当指定容量时就是有界,反之则无界由于其入队和出队分别两把锁,所以吞吐量通常高于ArrayBlockingQueue。Executors.newFixedThreadPool()就使用了此队列。

        1.3.3 SynchronousQueue

        不存储任何元素的阻塞队列,适合用于两个线程之间的协作,通常用于生产者和消费者之间直接的交换;Executors.newCachedThreadPool()就使用了此队列。

        其他队列不在此说了,有机会分享下并发类容器。

      1.4 TimeUnitkeepAliveTime

   TimeUnit是个枚举类,表示超时的时间单位,例如毫秒、秒、分、小时、天等;

         keepAliveTime标示空闲线程的最大存活时间,这两个参数是一起的。如果不设置allowCoreThreadTimeOut(true)的话只对非核心线程有作用。

        如果任务很多,且每个任务执行时间较短,执行频率也很高,可以适当调大时间,提高线程利用率。相反,如果任务不多,且执行频率很低,适当调小可回收空闲线程节省资源。

  1.5  ThreadFactory

    线程工厂,给当前线程池创建线程的工厂类;

   我们可以使用google的工具类自定义线程名称、是否守护线程等,代码及控制台打印如下:

package org.springblade.test;

import com.google.common.util.concurrent.ThreadFactoryBuilder;

import java.util.concurrent.*;

/**
 * @Auther: liuzujie
 * @Date: 2025/1/1 21:45
 * @Desc: 测试类
 */
public class ThreadPoolTest {
	//自定义线程工厂
	private static ThreadFactory threadFactory = new ThreadFactor
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值