以 java 线程池为例,简单了解下 线程池 的原理。
之所以要使用线程池,本质原因还是 线程 的创建和销毁太耗资源。
Java线程池主要核心类:java.util.concurrent.ThreadPoolExecutor。
它的 构造函数 需要我们重点关注下:
public ThreadPoolExecutor(
int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
每个入参含义如下:
- corePoolSize:核心线程数(即使线程空闲,也要保留的线程数)
- maximumPoolSize:最大线程数
- keepAliveTime & unit:超出corePoolSize的那部分线程,最大保留时间及其 时间单位
- workQueue:线程队列
- threadFactory:线程工厂
- handler:线程拒绝策略
这些参数的使用原理参考如下图:
其对应的核心代码逻辑如下:
BlockingQueue阻塞队列:
- ArrayBlockingQueue 数组实现的阻塞队列 构造函数需指定队列大小 入队和出队共用一把锁
- LinkedBlockingQueue 链表实现的阻塞队列 入队和出队是用不同的锁
- SynchronousQueue Each insert operation must wait for a corresponding remove operation by another thread, and vice versa. A synchronous queue does not have any internal capacity, not even a capacity of one.
RejectedExecutionHandler拒绝策略:
- AbortPolicy:抛出RejectedExecution Exception 异常
- DiscardPolicy:啥也不做(意味着任务被丢弃了)
- DiscardOldestPolicy:获取队列头的一条数据,然后丢掉,将当前任务放入队列
- CallerRunsPolicy:由调用者自己去执行这个任务