“开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 7 天,点击查看活动详情”
线程池参数
ThreadPoolExecutor(int corePoolSize,
int maximumPoolSize,
long keepAliveTime,
TimeUnit unit,
BlockingQueue<Runnable> workQueue,
ThreadFactory threadFactory,
RejectedExecutionHandler handler)
1.corePoolSize:核心线程池大小 2.maximumPoolSize:最大线程池大小 3.keepAliveTime:线程最大空闲时间 4.unit:时间单位 5.workQueue:线程等待队列 6.threadFactory:线程创建工厂 7handler:拒绝策略 当在execute(Runnable)方法中提交新任务并且少于corePoolSize线程正在运行时,即使其他工作线程处于空闲状态,会创建一个新线程来处理该请求。如果有多于corePoolSize但小于maximumPoolSize线程正在运行,则仅当队列已满时才会创建新线程。如果maximumPoolSize达到最大值会执行拒绝策略。
线程池拒绝策略
- 丢弃任务并且抛出异常(默认)
- 丢弃任务但是不抛出异常
- 丢弃队列中最早的任务,重新提交被拒绝的任务(要看是否允许丢弃老任务)
- 由调用线程来处理该任务,目的要让所有任务都执行完毕
worker线程
private final class Worker extends AbstractQueuedSynchronizer implements Runnable{
final Thread thread;//Worker持有的线程
Runnable firstTask;//初始化的任务,可以为null
}
thread是调用构造方法时通过ThreadFactory来创建线程,可以用来执行任务 firstTask是该线程传入的第一个任务,如果该值非null,则在创建初期就立即执行这个任务(对应核心线程情况) 如果该值为null,需要创建一个线程去执行work queue中的任务(非核心线程的创建) Worker线程被创建后就会不断去轮询获取任务去执行,核心线程可以无限轮询,非核心线程只能限时获取任务 当Worker线程无法获取到任务时,循环会结束,主动消除自身在线程池的引用
线程池使用一张Hash表持有线程的引用,通过删除,增加引用来控制线程的生命周期 如何判断线程是否在运行? Worker继承AQS,使用AQS实现独占锁功能,没有使用可重入锁ReentrantLock,依靠不可重入性反应线程现在的状态 线程回收请求执行lock()方法,尝试获取独占锁,获取成功说明线程在运行状态(那么就不能中断线程) 如果线程不是独占锁的状态,那就是空闲状态,说明没在处理任务,可以进行中断 线程池在执行shutdown方法或tryTerminate方法时会调用interruptIdleWorkers方法来中断空闲的线程 interruptIdleWorkers调用tryLock()判断线程是否处于空闲状态,如果处于空闲状态即可回收
手动实现线程池
/**
* @author Bruce
*/
public class MyThreadPool {
private AtomicInteger ct = new AtomicInteger(0);//当前执行任务的线程个数
private int corePoolSize;
private int maximumPoolSize;
private long keepAliveTime;
private TimeUnit unit;
private BlockingQueue<Runnable> taskQueue;
private RejectPolicy policy;
private ArrayList<MyWorker> workers = new ArrayList<>();
private volatile boolean isStopped;
private boolean useTimed;
public int getCt(){
return ct.get();
}
public MyThreadPool(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, RejectPolicy policy, int maxTasks) {
assert corePoolSize > 0;
assert maximumPoolSize > 0;
assert keepAliveTime >= 0;
assert maxTasks > 0;
this.corePoolSize = corePoolSize;
this.maximumPoolSize = maximumPoolSize;
this.keepAliveTime = keepAliveTime;
this.unit = unit;
this.taskQueue = new ArrayBlockingQueue<>(maxTasks);
this.policy = policy;
useTimed = keepAliveTime != 0;
}
/**
*
* @param runnable
* @param max 判断达到哪个阈值
* @return
*/
public synchronized boolean addWorker(Runnable runnable, boolean max){
if (ct.get() > corePoolSize && !max) return false;
if (ct.get() > maximumPoolSize && max) return false;
MyWorker worker = new MyWorker(runnable);
workers.add(worker);
Thread t = new Thread(worker, "ThreadPool-" + "Thread-" + ct.addAndGet(1));
t.start();
return true;
}
public void execute(Runnable runnable) throws InterruptedException{
checkPoolState();
if (addWorker(runnable, true) || !taskQueue.offer(runnable) || addWorker(runnable, false)) return;
if (!taskQueue.offer(runnable)){
reject(runnable);
}
}
private void reject(Runnable runnable) throws InterruptedException {
switch (policy){
case ABORT:
throw new RuntimeException("Task queue is full");
case DISCARD:
return;
case CALLER_RUN:
runnable.run();
case DISCARD_OLDEST:
taskQueue.poll();
execute(runnable);
}
}
public <V> RunnableFuture<V> submit(Callable<V> task) throws InterruptedException{
checkPoolState();
FutureTask<V> futureTask = new FutureTask<>(task);
execute(futureTask);
return futureTask;
}
// 强制关闭线程池
public synchronized void stop() {
isStopped = true;
for (MyWorker worker : workers) {
worker.stopWorker();
}
}
public synchronized void shutDown() {
// 先表示关闭线程池 线程就不能再向线程池提交任务
isStopped = true;
// 先等待所有的任务执行完成再关闭线程池
waitForAllTasks();
stop();
}
private void waitForAllTasks() {
// 当线程池当中还有任务的时候 就不退出循环
while (taskQueue.size() > 0) {
Thread.yield();
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
private void checkPoolState() {
if (isStopped){
throw new RuntimeException("thread pool has been stopped, so quit submitting task");
}
}
class MyWorker implements Runnable{
private Thread thisThread;
private final Runnable firstTask;
private volatile boolean isStopped;
public MyWorker(Runnable firstTask){
this.firstTask = firstTask;
}
@Override
public void run() {
firstTask.run();
thisThread = Thread.currentThread();
while (!isStopped){
try {
//useTimed判断 如果在一定时间内没有从队列中获取到任务,就返回null,线程随之退出,但要判断线程数不能小于核心线程数
Runnable task = useTimed ? taskQueue.poll(keepAliveTime, unit) : taskQueue.take();
if (task == null){
int i;
boolean exit = true;
if (ct.get() > corePoolSize){
do {
i = ct.get();
if (i <= corePoolSize){
exit = false;
break;
}
}while (!ct.compareAndSet(i, i - 1));//原子性记录当前线程的安全退出
if (exit){
return;
}
}else{
task.run();
}
}
} catch (InterruptedException e) {
throw new RuntimeException(e);
}
}
}
public synchronized void stopWorker() {
if (isStopped) {
throw new RuntimeException("thread has been interrupted");
}
isStopped = true;
thisThread.interrupt();
}
}
}