编程语言
首页 > 编程语言> > java 线程池实现原理

java 线程池实现原理

作者:互联网

ThreadPoolExecutor 继承了 AbstractExecutorService,成员变量 ctl 是个 Integer 的原子变量用来记录线程池状态 和 线程池中线程个数,类似于 ReentrantReadWriteLock 使用一个变量存放两种信息。

//用来标记线程池状态(高3位),线程个数(低29位)
//默认是RUNNING状态,线程个数为0
private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

//线程个数掩码位数,并不是所有平台int类型是32位,所以准确说是具体平台下Integer的二进制位数-3后的剩余位数才是线程的个数,
private static final int COUNT_BITS = Integer.SIZE - 3;

//线程最大个数(低29位)00011111111111111111111111111111
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

线程池状态含义:
RUNNING:接受新任务并且处理阻塞队列里的任务;
SHUTDOWN:拒绝新任务但是处理阻塞队列里的任务;
STOP:拒绝新任务并且抛弃阻塞队列里的任务,同时会中断正在处理的任务;
TIDYING:所有任务都执行完(包含阻塞队列里面任务)当前线程池活动线程为 0,将要调用 terminated 方法;
TERMINATED:终止状态,terminated方法调用完成以后的状态。
线程池状态转换:
1.RUNNING -> SHUTDOWN:显式调用 shutdown() 方法,或者隐式调用了 finalize(),它里面调用了 shutdown() 方法。
2.RUNNING or SHUTDOWN -> STOP:显式调用 shutdownNow() 方法时候。
3.SHUTDOWN -> TIDYING:当线程池和任务队列都为空的时候。
4.STOP -> TIDYING:当线程池为空的时候。
5.TIDYING -> TERMINATED:当 terminated() hook 方法执行完成时候。

线程池参数:
corePoolSize:线程池核心线程个数;
workQueue:用于保存等待执行的任务的阻塞队列;比如基于数组的有界 ArrayBlockingQueue,基于链表的无界 LinkedBlockingQueue,最多只有一个元素的同步队列 SynchronousQueue,优先级队列 PriorityBlockingQueue 等。
maximunPoolSize:线程池最大线程数量。
ThreadFactory:创建线程的工厂。
RejectedExecutionHandler:饱和策略,当队列满了并且线程个数达到 maximunPoolSize 后采取的策略,比如 AbortPolicy (抛出异常),CallerRunsPolicy(使用调用者所在线程来运行任务),DiscardOldestPolicy(调用 poll 丢弃一个任务,执行当前任务),DiscardPolicy(默默丢弃,不抛出异常)。
keeyAliveTime:存活时间。如果当前线程池中的线程数量比核心线程数量要多,并且是闲置状态的话,这些闲置的线程能存活的最大时间。
TimeUnit,存活时间的时间单位。

线程池的实现主要依赖以下以下类和方法:
Worker:实现了Runnable接口用于实现线程复用,线程执行的载体
addWorker:添加一个worker执行线程
RunWorker:执行worker中线程的run方法

worker中有一个Thread类的成员变量,这个线程就是worker要执行的线程。 runworker中是一个while循环,只要存在task或者可以获取到新的task就会继续执行

private final class Worker implements Runnable {
 
	final Thread thread;
 
	Runnable firstTask;
 
	Worker(Runnable firstTask) {
		this.firstTask = firstTask;
		this.thread = getThreadFactory().newThread(this);
	}
 
	public void run() {
		runWorker(this);
	}
 
	final void runWorker(Worker w) {
		Runnable task = w.firstTask;
		w.firstTask = null;
		while (task != null || (task = getTask()) != null){
		task.run();
	}
}
private Runnable getTask() {
    if(一些特殊情况) {
        return null;
    }
 
    Runnable r = workQueue.take();
 
    return r;
}
public void execute(Runnable command) {
    if (command == null)
        throw new NullPointerException();
 
     int c = ctl.get();
    // 当前线程数 < corePoolSize
    if (workerCountOf(c) < corePoolSize) {
        // 直接启动新的线程。
        if (addWorker(command, true))
            return;
        c = ctl.get();
    }
 
    // 活动线程数 >= corePoolSize
    // runState为RUNNING && 队列未满
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();
        // 再次检验是否为RUNNING状态
        // 非RUNNING状态 则从workQueue中移除任务并拒绝
        if (!isRunning(recheck) && remove(command))
            reject(command);// 采用线程池指定的策略拒绝任务
        // 两种情况:
        // 1.非RUNNING状态拒绝新的任务
        // 2.队列满了启动新的线程失败(workCount > maximumPoolSize)
    } else if (!addWorker(command, false))
        reject(command);
}
private boolean addWorker(Runnable firstTask, boolean core) {
 
    int wc = workerCountOf(c);
    if (wc >= (core ? corePoolSize : maximumPoolSize)) {
        return false;
    }
 
    w = new Worker(firstTask);
    final Thread t = w.thread;
    t.start();
}

标签:Runnable,java,队列,command,RUNNING,线程,firstTask,原理
来源: https://blog.csdn.net/weixin_39650169/article/details/114301915