常用线程池之--Executors.newSingleThreadExecutor(),单线程线程池
在该线程池中只创建一个核心线程,任务队列采用 LinkedBlockingQueue<Runnable>()链表的形式,执行多个任务时每次只执行一个任务,其余的任务进入任务队列等待。调用的构造器如下:

链表的默认大小为2^31-1


常用线程池之--Executors.newFixedThreadPool(num),固定大小的线程池
该线程池中创建指定大小的核心线程数,由核心线程依次执行线程任务,任务队列采用 LinkedBlockingQueue<Runnable>()链表的形式,

常用线程池之--Executors.newCachedThreadPool(),可缓冲线程池
线程池中创建2^31-1个非核心线程,线程在空闲时的存活时间为60s,任务队列采用SynchronousQueue<Runnable>()同步队列。


同步队列的构造过程如下:


自定义线程池
全参数的线程池构造器如下:

任务提交过程如下:

首先任务提交到核心线程执行,其次是进入任务队列,最后提交到非核心线程执行。但任务执行时先执行核心线程任务,其次是非核心线程中的任务,最后才是执行任务队列中的等待任务。

任务执行过程源码分析如下:

复杂参数详解如下:
1、BlockingQueue<Runnable> workQueue(必需):任务队列。通过线程池的 execute() 方法提交的 Runnable 对象将存储在该队列中,其采用阻塞队列实现。非空
常见的实现类:
- LinkedBlockingQueue<Runnable> 链表队列
底层使用链表存取数据,存储的数据格式如下:

创建链表阻塞队列时可指定链表大小,不指定时使用默认值,

存储当前数据item和下一个节点的引用next。该链表中维护两把锁,takelock(取数据)和putlock(存数据),实现读写分离,notEmpty和notFull分别标记当前队列非空和未满的状态,队列为空时种阻塞出队操作,队列已满时阻塞入队操作。
入队操作源码如下:如果当前元素数量已经达到链表容量,则阻塞put操作,反之当前元素入队;入队之后判断链表元素如果小于链表容量,唤醒当前阻塞的put线程;如果当前队列元素为0,调用signalNotempty()方法,阻塞take(取元素)操作,


出队操作源码如下:首先需要判断当前队列是否为空,如果为空阻塞当前取元素的操作,反之当前队头元素出队;然后判断元素个数,大于0则标记当前队列非空,执行takelock.unlock();如果队列元素达到最大值,执行signalNotfull()方法。阻塞put(添加元素)操作。


- SynchronousQueue<Runnable> 同步队列
同步队列存储任务的数据结构也是链表,构造同步队列时可通过参数指定当前队列是否公平(默认为非公平队列),公平队列遵循先进先出原则,创建队列;非公平队列遵循后进先出原则,创建栈。


线程安全的实现采用CAS+自旋的方式实现。存取数据都通过transfer方法。


transfer方法中根据携带的参数e是否为null判断当前请求为request(取数据) 模式还是data模式(存数据)。

- ArrayBlockingQueue 数组队列
底层采用数组进行数据存储,对垒读写过程中共用一把锁(java中只存储数组的首地址,读写操作的是同一个数组),读写互斥。当队列长度为0或maxsize时阻塞。长度为0,阻塞take操作,可执行入队操作,之后唤醒notEmpty;长度为数组最大容量,阻塞put操作,可执行出队操作,之后唤醒notFull。



- LinkedBlockingDeque 链表双端队列
维护一把锁,队首队尾都可以出队
- PriorityBlockingQueue 优先级阻塞队列
底层用数组和小顶二叉堆存储数据,且数组下标为0的位置不存储数据,可通过i/2获取当前下标为i元素的父元素下标。
入队时不发生阻塞(数组自动扩容),自下而上构建二叉堆。
出队时队列为空发生阻塞,自上而下构建二叉堆。
- DelayQueue 延时队列
底层数据结构与优先级队列类似,入队不发生阻塞,
出队,队列为空时阻塞;队列非空,不阻塞。
2、ThreadFactory threadFactory(可选参数): 用于指定为线程池创建新线程的方式;非空
3、RejectedExecutionHandler handler(可选):拒绝策略,当达到最大线程数时需要执行的饱和策略。非空。拒绝策略有四类型,如下图,四个类实现RejectedExecutionHandler接口,为ThreadPoolExecutor的静态内部类,创建对象的方式为new ThreadPoolExecutor.拒绝策略实现类();

-
AbortPolicy():该策略会抛出异常对象,需要处理该异常对象才能继续执行后续的程序。是默认的执行策略。

-
DiscardPolicy():直接丢弃当前任务,不进行任何操作

-
DiscardOldestPolicy():在线程池未关闭的情况下,从当前任务队列中丢弃最老的一个尚未执行的任务,并添加新的任务进队列。

-
CallerRunsPolicy():线程池关闭时直接丢弃当前任务,反之,使用主线程(main线程)直接执行当前任务。

2万+

被折叠的 条评论
为什么被折叠?



