线程池

170 阅读9分钟

一、简介

1、优点

降低资源消耗,通过重复利用已创建的线程降低线程创建和销毁造成的消耗

提高响应速度,当任务到达时不需要创建线程就能立即执行

提高线程的可管理性

2、使用

单个任务处理时间比较短

需要处理的任务数量很大

二、源码分析

1、ThreadPoolExecutor构造方法


字段含义:

1)corePoolSize:核心线程数量

2)maximumPoolSize:最大线程数量

3)wokeQueue:等待队列

4)keepAliveTime:线程池维护线程所允许的空闲时间

5)threadFactory:用来创建新线程

6)handler:拒绝策略

2、线程池的运行状态

private static final int RUNNING    = -1 << COUNT_BITS;
private static final int SHUTDOWN   =  0 << COUNT_BITS;
private static final int STOP       =  1 << COUNT_BITS;
private static final int TIDYING    =  2 << COUNT_BITS;
private static final int TERMINATED =  3 << COUNT_BITS;

1)RUNNING:能接收新提交的任务,能处理阻塞队列中的任务

2)SHUTDOWN:不再接收新提交的任务,可以继续处理阻塞队列中已保存的任务(线程池处于RUNNING状态时,调用shutdown()方法会使得线程池进入该状态)

3)STOP:不接收新提交的任务,也不处理队列中的任务,会中断正在处理任务的线程(线程池处于RUNNING或SHUTDOWN时,调用shutdownNow()方法会使得线程池进入该状态)

4)TIDYING:如果所有的任务都已终止,workerCount为0,线程池进入该状态

5)TERMINATED:线程池进入TIDYING状态后会调用terminated()方法进入该状态


3、基础属性

private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));

线程池内部使用一个变量维护两个值:允许状态(runState)和线程数量(workerCount),高3位保存runState,低29位保存workerCount。这样做可以避免出现不一致的情况时不必为了维护两者的一致而占用锁资源。

private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int CAPACITY   = (1 << COUNT_BITS) - 1;
//计算当前运行状态
private static int runStateOf(int c)     { return c & ~CAPACITY; }
//计算当前线程数量
private static int workerCountOf(int c)  { return c & CAPACITY; }
//通过状态和线程数生成ctl
private static int ctlOf(int rs, int wc) { return rs | wc; }

四、execute()提交任务

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();    
    }
    //如果当前线程池是运行状态并且任务添加到队列成功    
    if (isRunning(c) && workQueue.offer(command)) {
        int recheck = ctl.get();  
        //再次判断线程池到状态,如果不是运行状态,由于之前已经把command添加到队列中,需要移除              if (! isRunning(recheck) && remove(command))            
            reject(command);        
        else if (workerCountOf(recheck) == 0)            
            addWorker(null, false);    
    //线程池不是RUNNING状态或线程池是RUNNING状态但workerCOunt >= corePoolSize并且workQueue已满
    }else if (!addWorker(command, false))        
            reject(command);
}


五、addWorker()

在线程池中创建一个新但线程并执行,firstTask参数用于指定新增的线程执行的第一个任务,core参数为ture表示在新增线程时会判断当前活动线程数是否少于corePoolSize,false表示新增线程需要判断当前活动线程数是否少于maximumPoolSize

private boolean addWorker(Runnable firstTask, boolean core) {
    retry:  
    //第一层的循环是判断线程池的状态  
    for (;;) {        
        int c = ctl.get();        
        int rs = runStateOf(c);
        //rs >= SHUTDOWN表示此时不再接收新任务,考虑rs == SHUTDOWN时,这种情况下不再接收新的
        //任务,所以firstTask不为空时返回false;如果firstTask为空workQueue为空则返回false
        //因为队列中没有任务了,不需要再添加线程了。        
        if (rs >= SHUTDOWN && !(rs == SHUTDOWN && firstTask == null && ! workQueue.isEmpty()))
            return false;     
        //第二层的循环是更改线程数   
        for (;;) {            
            int wc = workerCountOf(c);            
            if (wc >= CAPACITY || wc >= (core ? corePoolSize : maximumPoolSize))
                return false;
            //通过CAS增加workerCount            
            if (compareAndIncrementWorkerCount(c))                
                break retry;            
            c = ctl.get();  // Re-read ctl   
            //如果是因为多线程失败则继续CAS,如果因为线程池状态改变,则重新判断线程池的状态         
            if (runStateOf(c) != rs)                
                continue retry;            
            // else CAS failed due to workerCount change; retry inner loop        
        }    
    }    
    boolean workerStarted = false;    
    boolean workerAdded = false;    
    Worker w = null;    
    try {        
        w = new Worker(firstTask);   
        //每一个Worker对象都会创建一个线程     
        final Thread t = w.thread;        
        if (t != null) {            
            final ReentrantLock mainLock = this.mainLock;            
            mainLock.lock();            
            try {                
                // Recheck while holding lock.                
                // Back out on ThreadFactory failure or if                
                // shut down before lock acquired.                
                int rs = runStateOf(ctl.get());  
                //rs < SHUTDOWN表示是RUNNING状态
                //如果rs是RUNNING状态或rs是SHUTDOWN状态并且firstTask为null,向线程池中添加线程
                if (rs < SHUTDOWN || (rs == SHUTDOWN && firstTask == null)) {
                    if (t.isAlive()) // precheck that t is startable
                        throw new IllegalThreadStateException();
                    //workers是一个HashSet
                    workers.add(w);                    
                    int s = workers.size();                    
                    if (s > largestPoolSize)                        
                        largestPoolSize = s;                    
                    workerAdded = true;                
                }            
            } finally {                
                mainLock.unlock();            
            }            
            if (workerAdded) {  
                //启动线程              
                t.start();                
                workerStarted = true;
            }        
        }    
    } finally {        
        if (! workerStarted)            
            addWorkerFailed(w);    
        }    
    return workerStarted;
}

内部类Worker

private final class Worker extends AbstractQueuedSynchronizer implements Runnable{
    private static final long serialVersionUID = 6138294804551838833L;
    final Thread thread;
    //保存传入的第一个任务
    Runnable firstTask;
    volatile long completedTasks;
    Worker(Runnable firstTask) {
        //把state设置为-1,因为AQS中默认的state是0,如果刚创建了一个Worker对象,还没有执行任务时
        //就不应该被中断
        setState(-1);
        this.firstTask = firstTask;
        //创建线程
        this.thread = getThreadFactory().newThread(this);
    }
    public void run() {
        runWorker(this);
    }    
    protected boolean isHeldExclusively() {
        return getState() != 0;
    }
    //实现独占锁,不允许重入
    //lock方法一旦获取独占锁,表示当前线程正在执行任务中
    //如果正在执行任务则不应该中断线程
    //如果线程不是独占锁的状态(空闲状态)说明它没有处理任务,这时可以对线程进行中断
    //线程池在执行shutdown方法或tryTerminate方法时会调用interruptldleWorkers方法来中断空闲
    //的线程,会使用tryLock方法来判断线程池中的线程是否是空闲状态
    //之所以设置为不可重入,是因为我们不希望任务在调用像setCorePoolSize这样的线程池控制方法时重新
    //获取锁
    protected boolean tryAcquire(int unused) {
        if (compareAndSetState(0, 1)) {
            setExclusiveOwnerThread(Thread.currentThread());
            return true;
        }
        return false;
    }
    protected boolean tryRelease(int unused) {
        setExclusiveOwnerThread(null);
        setState(0);
        return true;
    }
    public void lock()        { acquire(1); }
    public boolean tryLock()  { return tryAcquire(1); }
    public void unlock()      { release(1); }
    public boolean isLocked() { return isHeldExclusively(); }
    void interruptIfStarted() {
        Thread t;
        if (getState() >= 0 && (t = thread) != null && !t.isInterrupted()) {
            try {
                t.interrupt();
            } catch (SecurityException ignore) {
            }
        }
    }
}
final void runWorker(Worker w) {
    Thread wt = Thread.currentThread();
    Runnable task = w.firstTask;
    w.firstTask = null;
    w.unlock(); // allow interrupts
    //是否因为异常退出循环
    boolean completedAbruptly = true;
    try {
        //task为空或从队列中获取任务为空
        while (task != null || (task = getTask()) != null) {
            w.lock();
            // If pool is stopping, ensure thread is interrupted;
            // if not, ensure thread is not interrupted.  This
            // requires a recheck in second case to deal with
            // shutdownNow race while clearing interrupt
            //如果线程池正在停止,那么要保证当前线程是中断状态
            if ((runStateAtLeast(ctl.get(), STOP) ||
                 (Thread.interrupted() && runStateAtLeast(ctl.get(), STOP))) 
                 && !wt.isInterrupted()) 
                wt.interrupt();
                try {
                    beforeExecute(wt, task);
                    Throwable thrown = null;
                    try {
                        task.run();
                    } catch (RuntimeException x) {
                        thrown = x; throw x;
                    } catch (Error x) {
                        thrown = x; throw x;
                    } catch (Throwable x) {
                        thrown = x; throw new Error(x);
                    } finally {
                        afterExecute(task, thrown);
                    }
            } finally {
                task = null;
                w.completedTasks++;
                w.unlock();
            }
        }
        completedAbruptly = false;
    } finally {
        processWorkerExit(w, completedAbruptly);
    }
}

while循环不断的通过getTask()方法获取任务

如果线程池正在停止,那么要保证当前线程是中断状态,否则要保证当前线程不是中断状态

调用task.run()执行任务

如果task为null则跳出循环,执行processWorkerExit()方法

runWorker方法执行完毕,也代表着Worker中的run方法执行完毕,销毁线程

getTask从队列中获取任务

private Runnable getTask() {
    boolean timedOut = false; // Did the last poll() time out?
    for (;;) {
        int c = ctl.get();
        int rs = runStateOf(c);
        // Check if queue empty only if necessary.
        if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
            decrementWorkerCount();
            return null;
        }
        int wc = workerCountOf(c);
        // allowCoreThreadTimeOut默认是false,核心线程不允许超时
        boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
        //wc > maximumPoolSize可能是因为在此方法执行阶段同时执行了setMaximumPoolSizeff        //timed && timedOut如果为true表示当前操作需要进行超时控制,并且上次从阻塞队列中获取
        //任务发生了超时,如果有效线程数量大于1,或者队列是空的,那么尝试将workerCount减1
        
        if ((wc > maximumPoolSize || (timed && timedOut)) && (wc > 1 || workQueue.isEmpty())) {
            if (compareAndDecrementWorkerCount(c))
                return null;
            continue;
        }
        try {
            //根据timed来判断,如果为true则通过阻塞队列的poll方法进行超时控制,如果在keepAliveTime            //时间内没有获取到任务则返回null,否则通过take方法,如果这时队列为空,则take方法
            //会阻塞直到队列不为空
            Runnable r = timed ? workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :  workQueue.take();
            if (r != null)
                return r;
            //说明已经超时
            timedOut = true;
        } catch (InterruptedException retry) {
            timedOut = false;
        }
    }
}

getTask方法返回null时,在runWorker方法中会跳出while循环,然后执行processWorkerExit方法

private void processWorkerExit(Worker w, boolean completedAbruptly) {
    //completedAbruptly为true,则说明线程执行时出现了异常,需要将workerCount减1
    //如果没有出现异常说明在getTask方法中已经对workerCount进行了减1操作就不必再减了
    if (completedAbruptly) 
        decrementWorkerCount();
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        //统计完成对任务数
        completedTaskCount += w.completedTasks;
        //从workers中移除,表示从线程池中移除了一个工作线程
        workers.remove(w);
    } finally {
        mainLock.unlock();
    }
    //根据线程池对状态进行判断是否结束线程池
    tryTerminate();
    int c = ctl.get();
    //当线程池是RUNNING或SHUTDOWN状态时,如果worker是异常结束,那么会直接addWorker
    //如果allowCoreThreadTimeOut=true,并且等待队列有任务,至少保留一个worker    //如果allowCoreThreadTimeOut=false,workerCount不少于corePoolSize
    if (runStateLessThan(c, STOP)) {
        if (!completedAbruptly) {
            int min = allowCoreThreadTimeOut ? 0 : corePoolSize;
            if (min == 0 && ! workQueue.isEmpty())
                min = 1;
            if (workerCountOf(c) >= min)
                return; // replacement not needed
        }
        addWorker(null, false);
    }
}

六、结束线程池

final void tryTerminate() {
    for (;;) {
        int c = ctl.get();
        //不能终止对状态
        if (isRunning(c) || runStateAtLeast(c, TIDYING) || (runStateOf(c) == SHUTDOWN && ! workQueue.isEmpty()))
            return;
        if (workerCountOf(c) != 0) { // Eligible to terminate
            interruptIdleWorkers(ONLY_ONE);
            return;
        }
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            //设置TIDYING状态
            if (ctl.compareAndSet(c, ctlOf(TIDYING, 0))) {
                try {
                    terminated();
                } finally {
                    ctl.set(ctlOf(TERMINATED, 0));
                    termination.signalAll();
                }
                return;
            }
        } finally {
            mainLock.unlock();
        }
        // else retry on failed CAS
    }
}

shutdown方法要将线程池切换到SHUTDOWN状态,并调用interruptldleWorkers方法请求中断所有空闲到worker,最后调用tryTerminate尝试结束线程池

public void shutdown() {
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        //安全策略判断
        checkShutdownAccess();
        //切换为SHUTDOWN状态
        advanceRunState(SHUTDOWN);
        //中断所有空闲线程
        interruptIdleWorkers();
        onShutdown(); // hook for ScheduledThreadPoolExecutor
    } finally {
        mainLock.unlock();
    }
    tryTerminate();
}
public List<Runnable> shutdownNow() {
    List<Runnable> tasks;
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        checkShutdownAccess();
        advanceRunState(STOP);
        //中断所有线程
        interruptWorkers();
        取出队列中没有被执行对任务
        tasks = drainQueue();
    } finally {
        mainLock.unlock();
    }
    tryTerminate();
    return tasks;
}


               欢迎关注我的微信公众号,分享leetcode解题心得和Java后端的相关知识