栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > Java

线程池ThreadPoolExecutor

Java 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

线程池ThreadPoolExecutor

什么是线程池

线程池(Thread Pool)是一种基于池化思想管理线程的工具,经常出现在多线程服务器中,如MySQL。线程池维护着多个线程,等待着监督管理者分配执行的任务,简单来说,就是可管理和维护以及分配线程的“池子”。

线程池的优点

1)降低资源消耗:减少创建和销毁线程的次数,让每个线程都可以多次的使用。
2)提高响应速度:任务到达时,无需等待线程创建。
3)便于管理:根据系统情况调整线程的数量,防止消耗过多内存,使用线程池可以进行统一的分配、调优和监控。
4)可扩展:线程池具备可拓展性,允许开发人员向其中增加更多的功能。比如延时定时线程池ScheduledThreadPoolExecutor,就允许任务延期执行或定期执行。

线程池运行的状态

线程池运行的状态,并不是用户显式设置的,而是伴随着线程池的运行,由内部来维护,有五种状态:RUNNING、SHUTDOWN、STOP、TIDYING、TERMINATED。

运行状态说明
RUNNING线程池的初始化状态是RUNNING,处在RUNNING状态时,能够接收新任务,以及对已添加的任务进行处理
SHUTDOWN调用线程池的shutdown()接口时,线程池由RUNNING -> SHUTDOWN,线程池处在SHUTDOWN状态时,不接收新任务,但能处理已添加的任务
STOP调用线程池的shutdownNow()接口时,线程池由(RUNNING or SHUTDOWN ) -> STOP,线程池处在STOP状态时,不接收新任务,不处理已添加的任务,并且会中断正在处理的任务
TIDYING当线程池在SHUTDOWN状态下,阻塞队列为空并且线程池中执行的任务也为空时,就会由 SHUTDOWN -> TIDYING,当线程池变为TIDYING状态时,会执行钩子函数terminated()
TERMINATED线程池处在TIDYING状态时,执行完terminated()之后,就会由 TIDYING -> TERMINATED,线程池彻底终止
线程池核心参数

ThreadPoolExecutor继承自AbstractExecutorService,而AbstractExecutorService实现了ExecutorService接口,线程池的构造方法如下:

    public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

参数说明:

参数说明
corePoolSize核心线程数
maximumPoolSize最大线程数
keepAliveTime线程空闲时间
TimeUnit时间单位
workQueue任务队列/阻塞队列
ThreadFactory线程工厂
RejectedExecutionHandler拒绝策略
任务队列/阻塞队列

使用不同的队列可以实现不一样的任务存取策略。阻塞队列有下面几种:

名称描述
ArrayBlockingQueue一个数组实现的有界阻塞队列,先进先出的原则,支持公平锁和非公平锁
LinkedBlockingQueue一个由链表结构组成的有界队列,默认长度Integer.MAX_VALUE,先进先出的原则
PriorityBlockingQueue一个支持线程优先级排序的无界队列,默认自然序列进行排序,也可以自定义compareTo()方法指定排序,不能保证同优先级元素的顺序
DelayQueue一个实现PriorityBlockingQueue实现延时获取的无界队列,在创建元素时可以指定多久才能从队列获取当前元素
SynchronousQueue一个不存储元素的队列,每一个put操作必须等到task操作,否则不能添加元素,支持公平锁和非公平锁 ,这个线程池根据需要(新任务来时)创建线程,如果有空闲线程则会重复使用,线程空闲60s后被回收
LinkedTransferQueue一个由链表结构组成的无界阻塞队列,相比其他队列多了transfer和tryTransfer方法
LinkedBlocingDeque一个由链表结构组成的双向阻塞队列,队列头和尾部都可以添加或删除元素,多线程并发时可将锁的竞争最多降低一半
拒绝策略

拒绝策略是线程池的保护部分,线程池有一个最大的容量,当线程池的任务缓存队列已满,并且线程池中的线程数目达到maximumPoolSize时,就需要拒绝掉该任务,采取任务拒绝策略,保护线程池。拒绝策略是一个接口:

public interface RejectedExecutionHandler {
	void rejectedExecution(Runnable r, ThreadPoolExecutor executor);
}

用户可以通过实现这个接口去定制拒绝策略,也可以选择JDK提供的四种已有拒绝策略,其特点如下:

名称描述
ThreadPoolExecutor.AbortPolicy丢弃任务并抛出RejectedExecutionException异常,线程池默认拒绝策略
ThreadPoolExecutor.DiscardPolicy丢弃任务不抛出异常
ThreadPoolExecutor.DiscardOldestPolicy丢弃队列最前面的任务,然后重新提交被拒绝的任务
ThreadPoolExecutor. CallerRunsPolicy由调用线程(提交任务的线程)处理该任务
线程池的执行顺序

1)首先检测线程池运行状态,如果不是RUNNING,则直接拒绝,线程池要保证在RUNNING的状态下执行任务。
2)如果workerCount(已创建的线程) < corePoolSize,则创建并启动一个线程来执行新提交的任务。
3)如果workerCount >= corePoolSize,且线程池内的阻塞队列未满,则将任务添加到该阻塞队列中。
4)如果workerCount >= corePoolSize && workerCount < maximumPoolSize,且线程池内的阻塞队列已满,则创建并启动一个线程来执行新提交的任务。
5)如果workerCount >= maximumPoolSize,并且线程池内的阻塞队列已满, 则根据拒绝策略来处理该任务, 默认的处理方式是直接抛异常。

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/915376.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号