线程池

线程池

初始化线程池:

ThreadPoolExecutor executor = new ThreadPoolExecutor(10,10,10,TimeUnit.SECONDS, new LinkedBlockingQueue<>(10000),
                    Executors.defaultThreadFactory(), new ThreadPoolExecutor.AbortPolicy());

参数补充说明:

名称 类型 说明
corePoolSize int 核心线程池大小
maximumPoolSize int 最大线程数大小
keepAliveTime long 线程最大空闲时间
unit TimeUnit 时间单位
workQueue BlockingQueue 线程等待队列
threadFactory ThreadFactory 线程创建工厂
handler RejectedExecutionHandler 拒绝策略,默认为AbortPolicy

缓冲队列补充说明:

名称 说明 备注
ArrayBlockingQueue 构造必须指定大小 其所含的对象是FIFO顺序排序的
LinkedBlockingQueue 大小不固定的BlockingQueue,其构造时指定大小,默认为Integer.MAX_VALUE 其所含的对象是FIFO顺序排序的
PriorityBlockingQueue 类似LinkedBlockingQueue 排序是自然排序或按照对象的Comparetor排序
SynchronizedQueue 特殊队列,存取必须是交替进行

ThreadPoolExecutor提供的拒绝策略补充说明:

名称 说明 备注
AbortPolicy 拒绝任务,直接抛出异常 默认策略
CallerRunsPolicy 由主线程去执行任务
DiscardPolicy 丢弃任务,不抛出异常,也不执行 方法实现为空
DiscardOldestPolicy 抛弃队列中最旧的任务,然后将任务加入队列中

Executors线程池工具类

        // 创建定长的线程池,必须根据实际情况估算出线程的数量
        Executors.newFixedThreadPool(3);
        // 创建一个可缓存的线程池,线程数量不做限制可根据需要灵活回收空闲线程,需要通过控制并发任务的数量来控制线程的数量
        Executors.newCachedThreadPool();
        // 创建一个定长的线程池,支持定时以及周期性执行的任务的需求
        Executors.newScheduledThreadPool(5);
        // 创建一个单线程的线程池,如果唯一的线程因异常而结束会创建一个新线程来替代它
        Executors.newSingleThreadExecutor();
        Executors.newSingleThreadScheduledExecutor();
        // 创建一个具有抢占式操作的线程池
        Executors.newWorkStealingPool();

Executor框架集

ExecutorService

juc.ExecutorService继承自Executor接口

ThreadPoolExecutor

成员变量:ctl:

// 表示两种含义:
// ①:workerCount:worker计数,表示正在处理中的任务
// ②:runState:运行状态,共5种见下表
// Integer值分32位,前3位是runState,后29位是workerCount
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

运行状态值

运行状态 十进制 二进制 说明 备注
RUNNING -1<<29 111000...000000 运行中 二进制为补码表示
SHUTDOWN 0<<29 000000...000000 关闭,不再接受新任务,但仍然会处理排队任务 正数的原码,反码,补码均相同
STOP 1<<29 001000...000000 停止,不接受新任务及排队任务,中断处理中的任务
TIDYING 2<<29 010000...000000 整理,所有任务终止,workerCount归0进入该状态 之后将调用terminal()钩子方法
TERMINATED 3<<29 011000...000000 终止,terminal()已执行完成

更多细节还待学习...

核心线程数与最大线程数怎么配?

IO密集型任务:cpu核心数*2

为什么是这个数?

理想线程数 = ((CPU运算时间+IO等待时间) / CPU运算时间) * CPU核心数,CPU和IO时间相等时就是2倍CPU核心数

CPU密集型任务:cpu核心数+1,即:Runtime.getRuntime().availableProcessors()+1

为什么是cpu核心数+1?

《Java并发编程实战》一书中给出的原因是:即使当计算(CPU)密集型的线程偶尔由于页缺失故障或者其他原因而暂停时,这个“额外”的线程也能确保 CPU 的时钟周期不会被浪费。

线程池参数可通过相应的set方法动态修改,任务队列大小不支持动态修改,但可自定义阻塞队列来实现(容量大小不使用final修饰,提供set方法)

当修改最大线程数时如果新只小于当前值,则只会回收闲置线程

线程池被创建后里面有线程吗?如果有的话,有什么方法对线程池进行预热吗?

线程池被创建后如果没有任务过来,里面是不会有线程的。如果需要预热的话可以调用下面的两个方法:

// 启动全部核心线程,返回启动的数量
public int prestartAllCoreThreads()
// 启动一个核心线程,如果所有的
public boolean prestartCoreThread()

核心线程数会被回收吗?需要什么设置?

核心线程数默认是不会被回收的,如果需要回收核心线程数,需要调用下面的方法:

// allowCoreThreadTimeOut 该值默认为 false
public void allowCoreThreadTimeOut(boolean value)
posted @   Abserver  阅读(50)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
点击右上角即可分享
微信分享提示