资讯专栏INFORMATION COLUMN

java线程池——ThreadPoolExecutor源码解析

TerryCai / 3382人阅读

摘要:将线程池状态置为并不会立即停止,停止接收外部的任务,内部正在跑的任务和队列里等待的任务,会执行完,才真正停止。将线程池状态置为。

在Java中,我们经常使用的线程池就是ThreadPoolExecutor,此外还有定时的线程池ScheduledExecutorService(),但是需要注意的是Executors.newCachedThreadPool()的线程是没有上届的,在使用时,需要注意,因为没有办法控制线程数量,可能会导致线程的溢出。
一个简单的示例

1 ThreadPoolExecutor提供了四个构造函数:
//五个参数的构造函数
public ThreadPoolExecutor(int corePoolSize,

                      int maximumPoolSize,
                      long keepAliveTime,
                      TimeUnit unit,
                      BlockingQueue workQueue)

//六个参数的构造函数
public ThreadPoolExecutor(int corePoolSize,

                      int maximumPoolSize,
                      long keepAliveTime,
                      TimeUnit unit,
                      BlockingQueue workQueue,
                      ThreadFactory threadFactory)

//六个参数的构造函数
public ThreadPoolExecutor(int corePoolSize,

                      int maximumPoolSize,
                      long keepAliveTime,
                      TimeUnit unit,
                      BlockingQueue workQueue,
                      RejectedExecutionHandler handler)

//七个参数的构造函数
public ThreadPoolExecutor(int corePoolSize,

                      int maximumPoolSize,
                      long keepAliveTime,
                      TimeUnit unit,
                      BlockingQueue workQueue,
                      ThreadFactory threadFactory,
                      RejectedExecutionHandler handler)

2 各个参数解释

int corePoolSize:该线程池中核心线程数最大值。

核心线程:线程池新建线程的时候,如果当前线程总数小于corePoolSize,则新建的是核心线程,如果超过corePoolSize,则新建的线程即为非核心线程,核心线程默认情况下会一直存在线程池中,即使这个线程什么也不干,如果指定ThreadPoolExecutor的allowCoreThreadTimeOut这个属性是true,那么核心线程如果长时间不干活的话,超过一定时间,就会被销毁掉。

int maximumPoolSize:该线程池中线程的最大值

long keepAliveTime :该线程池中非核心线程闲置超时时间

一个非核心线程,如果不干活的时间超过这个参数所设定的时长,就会被销毁,如果设置allowCoreThreadTimeOut = true,那么核心线程超过所设定的时长,那么也会销毁掉。

TimeUnit unit:keepAliveTime的单位

TimeUnit是一个枚举类型,其包括:NANOSECONDS : 1微毫秒 = 1微秒 / 1000,MICROSECONDS : 1微秒 = 1毫秒 / 1000,MILLISECONDS : 1毫秒 = 1秒 /1000,
SECONDS : 秒,MINUTES : 分,HOURS : 小时,DAYS : 天。

BlockingQueue workQueue:该线程池中的任务队列:维护等待执行的Runnable对象。

如果当所有的核心线程都在干活时,新添加的任务会被添加到这个队列中等待处理,如果队列满了,则新建非核心的线程执行任务。常用的workQueue类型。

SynchronousQueue:这个队列接收到任务的时候,会直接提交给线程处理,而不会保留它,如果线程都在工作,那就新建一个线程来处理这个任务,所以为了保证不出现<线程数达到了maximumPoolSize而不能新建线程>的错误,使用这个类型队列的时候,maximumPoolSize一般指定成Integer.MAX_VALUE,即无限大。

LinkedBlockingQueue:这个队列接收到任务的时候,如果线程小于核心线程,则新建核心线程来处理任务,如果当前线程等于核心线程数,则进入队列中等待。由于这个队列没有最大值限制,即所有超过核心线程数的任务都会被添加到队列中去,这也导致maximumPoolSize的设定失效,因为总线程数永远不会超过corePoolSize

ArrayBlockingQueue:可以设定队列的长度,接收到任务的时候,如果没有达到corePoolSize的值,则新建线程执行任务,如果达到了,则入队等候,如果队列已满,则新建线程执行任务,如果线程数到了maximumPoolSize,并且队列中也满了,则发生错误。

DelayQueue:队列中元素必须实现Delayed接口,这就意味着你传进去的任务必须实现

Delayed接口,这个队列接收到任务时,首先先入队,只有达到指定的延时时间,才会执行任务。

ThreadFactory threadFactory:创建线程的方式,这是一个接口,你new它的时候需要实现它的Thread newThread(Runnable r)方法,一般用不上。

RejectedExecutionHandler handler:这玩意儿就是抛出异常专用的,比如上面提到的两个错误发生了,就会由这个handler抛出异常,根本用不上。

3 常用API解释:

public void execute(Runnable command)

将来某个时候执行给定的任务。任务可以在新线程中执行,也可以在现有的池线程中执行。如果无法提交任务以供执行,或者因为该执行器已经关闭,或者因为其容量已经达到,则该任务由当前{RejectedExecutionHandler}处理。

public void shutdown()

将线程池状态置为SHUTDOWN,并不会立即停止,停止接收外部submit的任务,内部正在跑的任务和队列里等待的任务,会执行完,才真正停止。

public List shutdownNow()

将线程池状态置为STOP。企图立即停止,事实上不一定,跟shutdown()一样,先停止接收外部提交的任务,忽略队列里等待的任务,尝试将正在跑的任务interrupt中断,返回未执行的任务列表。

public boolean awaitTermination(long timeout, TimeUnit unit)

当前线程阻塞,直到等所有已提交的任务(包括正在跑的和队列中等待的)执行完,或者等超时时间到,或者线程被中断,抛出InterruptedException,然后返回true(shutdown请求后所有任务执行完毕)或false(已超时)。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/71979.html

相关文章

  • 后端ing

    摘要:当活动线程核心线程非核心线程达到这个数值后,后续任务将会根据来进行拒绝策略处理。线程池工作原则当线程池中线程数量小于则创建线程,并处理请求。当线程池中的数量等于最大线程数时默默丢弃不能执行的新加任务,不报任何异常。 spring-cache使用记录 spring-cache的使用记录,坑点记录以及采用的解决方案 深入分析 java 线程池的实现原理 在这篇文章中,作者有条不紊的将 ja...

    roadtogeek 评论0 收藏0
  • 追踪解析 ThreadPoolExecutor 源码

    摘要:的前位数用来表示线程的数量,后面三位用来表示线程池的状态。线程池的状态有五种,分别是,根据单词就能猜出大概。并且为了考虑性能问题,线程池的设计没有使用悲观锁关键字,而是大量使用了和机制。 零 前期准备 0 FBI WARNING 文章异常啰嗦且绕弯。 1 版本 JDK 版本 : OpenJDK 11.0.1 IDE : idea 2018.3 2 ThreadPoolExecutor ...

    gaomysion 评论0 收藏0
  • 线程运行模型源码解析

    摘要:那么线程池到底是怎么利用类来实现持续不断地接收提交的任务并执行的呢接下来,我们通过的源代码来一步一步抽丝剥茧,揭开线程池运行模型的神秘面纱。 在上一篇文章《从0到1玩转线程池》中,我们了解了线程池的使用方法,以及向线程池中提交任务的完整流程和ThreadPoolExecutor.execute方法的源代码。在这篇文章中,我们将会从头阅读线程池ThreadPoolExecutor类的源代...

    MockingBird 评论0 收藏0
  • Java线程

    摘要:线程池概述什么是线程池就是将多个线程放在一个池子里面所谓池化技术然后需要线程的时候不是创建一个线程而是从线程池里面获取一个可用的线程然后执行我们的任务线程池的优势降低资源消耗通过重复利用已创建的线程降低线程创建和消耗提供响应速度当任务到达时 线程池概述 什么是线程池 就是将多个线程放在一个池子里面(所谓池化技术),然后需要线程的时候不是创建一个线程,而是从线程池里面获取一个可用的...

    darkerXi 评论0 收藏0
  • Java线程架构(一)原理和源码解析

    摘要:在前面介绍的文章中,提到了关于线程池的创建介绍,在文章之系列外部中第一部分有详细的说明,请参阅文章中其实说明了外部的使用方式,但是没有说内部是如何实现的,为了加深对实现的理解,在使用中可以放心,我们这里将做源码解析以及反馈到原理上,工具可 在前面介绍JUC的文章中,提到了关于线程池Execotors的创建介绍,在文章:《java之JUC系列-外部Tools》中第一部分有详细的说明,请参...

    wthee 评论0 收藏0

发表评论

0条评论

TerryCai

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<