线程池,你知多少【java线程高并发提升三】

上文链接:锁的智慧【java线程高并发提升二】

1、线程池是个什么东西?

线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在创建线程后自动启动这些任务。线程池线程都是后台线程。每个线程都使用默认的堆栈大小,以默认的优先级运行,并处于多线程单元中。如果某个线程在托管代码中空闲(如正在等待某个事件),则线程池将插入另一个辅助线程来使所有处理器保持繁忙。如果所有线程池线程都始终保持繁忙,但队列中包含挂起的工作,则线程池将在一段时间后创建另一个辅助线程但线程的数目永远不会超过最大值。超过最大值的线程可以排队,但他们要等到其他线程完成后才启动。

2、线程池的五种状态?

废话不说,直接上代码(代码在RejectedExecutionHandler -》rejectedExecution -》DiscardPolicy中)。

状态介绍RUNNING运行状态SHUTDOWN关闭状态,此状态下线程池不在接收新任务,只处理已添加任务。STOP停止状态,此状态下线程池停止所有任务。TIDYING整体桩体,此状态下线程池中任务数为0TERMINATED终结状态

各个状态转换如下:

3、线程池为什么这么创建、参数几何?

线程池创建过程如下:

接下来我们要开始讲述源码了!!!

该方法返回一个ThreadPoolExecutor对象。

ThreadPoolExecutor:线程池程序。定位到源码:

ThreadPoolExecutor可以设置参数及作用如下(相应源码可以自行定位查看):

参数名作用corePoolSize核心线程数量maximumPoolSize最大可容载线程数量keepAliveTime线程中空闲线程最长不释放时间(0表示一直不释放)workQueue存放等待执行的任务threadFactory线程池创建工厂,用于创建具体线程,默认实现为:defaultThreadFactory()defaultHandler当workQuery无法新加任务时,提供拒绝策略,默认拒绝策略:AbortPolicy(抛出异常)

defaultHandler:处理策略,在线程池程序调用execute后通过reject(command)可以设置相应拒绝策略。

4、线程池执行机制真是这样的!

对以上源码的描述:调用execute方法后,检查线程池的运行状态和工作线程数量,如果工作线程的线程数少于核心线程数,则会创建一个新的线程来执行给定的任务,调用addWorker来执行任务,如果线程池线程数量超过核心线程数量,把任务放到工作任务队列中,若工作队列未溢出,则添加任务,添加时重新检查线程池状态,如果没有继续运行(不是RUNNING状态)就把任务移除,使用拒绝策略来处理当前任务;否则将创建或唤醒工作线程来执行任务(线程池非RUNNING状态或添加任务失败后,使用拒绝策略来处理当前任务)。

5、线程池中的LinkedBlockingQueue阻塞队列。

(1) 接口及类继承展示。

(2)属性讲述

名称类型含义capacityint队列长度countAtomicInteger队列元素数量headNode头结点lastNode尾节点takeLockReentrantLock取出节点锁notEmptyCondition用以唤醒取出某节点的线程putLockReentranLock添加节点的锁notFullCondition用以唤醒某节点的线程

(3)队列添加、取出元素

方法总览:

方法作用介绍boolean add(E e)添加元素底层调用offer(E e)boolean offer(E e)添加元素队列满则返回失败,否则获取锁去添加元素boolean affer(E e,long timeout,TimeUnit unit)添加元素,超时返回队列未满等同offer;队列已满则等待指定时间,错误则返回boolean put(E e)阻塞地添加元素阻塞等待直到完成添加元素E peek()取出元素仅仅获取元素不删除E pool()取出元素,并删除队列中该元素E pool(long timeout,timeUnit unit)未超时前,取出元素,并删除队列中该元素队列不为空,与pool相同,队列空则等待制定时间否则返回空E take()阻塞地取出元素一直阻塞直到取出元素

6、线程中的ScheduledExecutorService预执行服务

该类应用于定时执行异步任务、周期性执行异步任务,需要注意异常处理,当抛出异常时,任务将终止周期性执行。

7、java中常用的线程池。

(1)固定线程数量的线程池

Executors.newFixedThreadPool创建固定线程线程池,源码中核心线程数和可容载最大线程数相同,当达到核心线程数后,空闲线程不会因超时而被终止或释放,且每添加一个任务后,会将任务添加到工作任务队列,线程池创建一个线程,线程数等于核心线程数时,不会再创建线程。

(2)单线程的线程池

通过Executors.newSingleThreadExecutor创建,由源码可知核心线程数和最大线程数一样,且均为1,即只有一个线程在执行队列的工作任务,注意该方法使用了FinalizableDelegatedExecutorService代理来创建线程池。

(3)可缓存的线程池

Executors.newCachedThreadPool创建可缓存的线程池,核心线程数为0,最大线程数为无限大(上面源码课件),空闲线程可以超时存在60s,使用SynchronousQueue同步队列(在添加任务时需同步有另一个工作线程来使用这个任务,否则无法添加)。

(4)定时执行的线程池

Executors.newScheduledThreadPool创建定时线程,可指定核心线程数,最大线程数为无限大,核心线程数空闲不会超时回收,使用了DelayedWorkQueue延时队列,通过延时队列控制时间执行线程。

8、机票系统多线程+Future运行实例


上述算法模拟获取机票售卖公司售卖票的过程,通过Future获取获得的信息,因此简单叙述下Future的运行原理。

Future在主线程阻塞等待时将线程池中的Callable执行结果同步共享变量到FutureTask实现获取信息。Future使用的场景是:会出现主线程阻塞超时等待的场景,不使用场景:只有一个任务,主线程不会出现阻塞等待的场景。

下文链接:两分钟了解ThreadLocal机制【java线程高并发提升四】

你可能感兴趣的:(线程池,你知多少【java线程高并发提升三】)