线程池源码分析

一些静态变量的含义

	// -536870912
	private final AtomicInteger ctl = new AtomicInteger(ctlOf(RUNNING, 0));
	private static final int COUNT_BITS = Integer.SIZE - 3;

	/*
		1->0000 0000 0000 0000 0000 0000 0000 0001
		左移29位
		 ->0010 0000 0000 0000 0000 0000 0000 0000
		 =线程池容量:1 * 2的29次方 - 1
	
		536870911
	*/
    private static final int CAPACITY   = (1 << COUNT_BITS) - 1;

    /*
    	-1->1000 0000 0000 0000 0000 0000 0000 0001
    	补码:1111 1111 1111 1111 1111 1111 1111 1111
    	左移29位
    	  ->1110 0000 0000 0000 0000 0000 0000 0000
    	原码:1001 0000 0000 0000 0000 0000 0000 0000
    	补码:1110 0000 0000 0000 0000 0000 0000 0000

		-536870912
		运行状态
    */
    private static final int RUNNING    = -1 << COUNT_BITS;

	/*
		0->0000 0000 0000 0000 0000 0000 0000 0000
		关闭状态,拒绝添加任务,任务队列中的人物还可继续执行
	*/
    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;

构造方法

ThreadPoolExecutor

  • ThreadPoolExecutor:有多个重载构造器,区别在于参数个数不同,最终都是执行下面的构造方法
  • 参数介绍:
    1、corePoolSize:核心线程数,核心线程默认是无超时时间,但可通过allowsCoreThreadTimeOut(boolean value)设置核心线程是否可超时
    2、maximumPoolSize:最大线程数,包括核心+非核心线程,当队列满载时,才会创建非核心线程来零时处理任务,如果corePoolSize = maximumPoolSize,则表示只有核心线程数
    3、keepAliveTime:线程的超时时长
    4、unit:超时时长的单位
    5、workQueue:任务队列
    6、threadFactory:线程工厂,默认是DefaultThreadFactory
    7、handler:拒绝策略,当线程数达到最大线程数时,且任务队列满载时,会执行拒绝策略,默认是AbortPolicy,还有CallerRunsPolicy、DiscardPolicy、DiscardOldestPolicy以及自定义拒绝策略
	public ThreadPoolExecutor(int corePoolSize,
                              int maximumPoolSize,
                              long keepAliveTime,
                              TimeUnit unit,
                              BlockingQueue<Runnable> workQueue,
                              ThreadFactory threadFactory,
                              RejectedExecutionHandler handler) {
        if (corePoolSize < 0 ||
            maximumPoolSize <= 0 ||
            maximumPoolSize < corePoolSize ||
            keepAliveTime < 0)
            throw new IllegalArgumentException();
        if (workQueue == null || threadFactory == null || handler == null)
            throw new NullPointerException();
        this.corePoolSize = corePoolSize;
        this.maximumPoolSize = maximumPoolSize;
        this.workQueue = workQueue;
        this.keepAliveTime = unit.toNanos(keepAliveTime);
        this.threadFactory = threadFactory;
        this.handler = handler;
    }

Worker

  • Worker:本身就是一个Runnable对象,其构造方法中通过线程工厂创建一个线程,并添加runnable
	private final class Worker extends AbstractQueuedSynchronizer
        implements Runnable
    {
    	...
		Worker(Runnable firstTask) {
	            setState(-1); // inhibit interrupts until runWorker
	            this.firstTask = firstTask;
	            this.thread = getThreadFactory().newThread(this);
	        }
	   	...
	}

核心API

  • execute:添加任务到线程池中,先校验执行任务数量是否超过核心线程,
    1、如果没有就将runnable包装到Worker中,开启线程去执行Worker中的runWorker()
    2、 如果线程创建、开启失败、超过了核心线程数,就检查线程池的状态是running,将runnable添加到任务队列wokerQueue的任务队列中,等待被执行
    3、如果线程池不是运行状态,就执行拒绝策略
    	public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        int c = ctl.get();
        // 核心1:工作线程未超过核心线程就直接创建新线程处理
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        // 核心2:超过核心线程数,任务添加到任务队列中,等待空闲线程执行
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            // 线程池非运行状态,则移除任务,执行拒绝策略
            if (! isRunning(recheck) && remove(command))
                reject(command);
            // 
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        // 核心3:当任务队列满了,且没有超过最大线程数,就创建一个线程进行处理,如果失败则走拒绝策略
        else if (!addWorker(command, false))
            reject(command);
    }
    
  • addWorker:校验线程池状态、线程数量是否达上限,满足则创建新线程并开启线程执行任务
    	private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);
            // 校验线程池状态,且特定条件校验任务队列为null
            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;
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                c = ctl.get();  // Re-read ctl
                if (runStateOf(c) != rs)
                    continue retry;
            }
        }
        ...
        try {
        	// 核心1:创建线程及关联任务
            w = new Worker(firstTask);
            final Thread t = w.thread;
            if (t != null) {
            	// 核心2:线程池中实现线程安全是使用Lock锁,而并非synchronized同步机制
                final ReentrantLock mainLock = this.mainLock;
                mainLock.lock();
                try {
                    int rs = runStateOf(ctl.get());
    
                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                        if (t.isAlive()) // precheck that t is startable
                            throw new IllegalThreadStateException();
                        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;
    }
    
  • runWorker:要么执行创建线程时绑定的任务,要么就是从等待队列中获取,通过while循环来延续当前线程的存活时间,当未获取到任务时,将结束while循环,当前线程执行结束
    	final void runWorker(Worker w) {
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;
        w.firstTask = null;
        w.unlock(); // allow interrupts
        boolean completedAbruptly = true;
        try {
        	// 核心1:获取线程绑定的任务/从任务队列中获取
            while (task != null || (task = getTask()) != null) {
                w.lock();
                if ((runStateAtLeast(ctl.get(), STOP) ||
                     (Thread.interrupted() &&
                      runStateAtLeast(ctl.get(), STOP))) &&
                    !wt.isInterrupted())
                    wt.interrupt();
                try {
                	// 钩子函数,任务执行前干些什么事,可通过自定义线程池实现
                    beforeExecute(wt, task);
                    Throwable thrown = null;
                    try {
                        // 执行任务run()
                        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 {
        	// 线程结束后,清空worker对象
            processWorkerExit(w, completedAbruptly);
        }
    }
    
  • getTask:从任务队列中拿任务;根据线程是否有超时限制,分别通过workQueue.poll()和workQueue.take()获取任务,二者区别在于,poll()当超过等待时间则返回一个null,而take()则是一直等待,直到有内容可返回
    	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:核心线程是否有超时
            // 执行任务的线程数超过核心线程数,就默认当前的线程为非核心线程,
            // 这样当没有任务可执行时就结束当前线程,当剩下线程数小于等于核心线程,则均默认为核心线程
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;
    
            if ((wc > maximumPoolSize || (timed && timedOut))
                && (wc > 1 || workQueue.isEmpty())) {
                if (compareAndDecrementWorkerCount(c))
                    return null;
                continue;
            }
    
            try {
            	// 等待从任务队列中获取任务
                Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                    workQueue.take();
                if (r != null)
                    return r;
                timedOut = true;
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
    }
    
  • shutDown:关闭线程池,所谓关闭,则是无法在继续添加新的任务;首先是更改线程池的状态为SHUTDOWN,其次中断未在执行任务的线程
    	public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            checkShutdownAccess();
            // 更改线程池状态,保证在添加任务时,无法继续添加
            advanceRunState(SHUTDOWN);
            // 中断空闲的线程,通过worker.unLock()未对线程上锁来判断是否为空闲
            interruptIdleWorkers();
            // 钩子函数,可在自定义线程池中监听关闭线程池
            onShutdown();
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
    }
    
  • shutDownNow:关闭线程池,并返回任务队列中为执行的任务;首先也是更改线程池的状态为STOP,其次中断所有的线程,包括正在执行任务的线程,最后再将为执行的任务队列的任务返回
    	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;
    }
    

考点1:shutDown和shutDownNow的区别?1、前者无返回值,后者返回任务队列中未执行的任务列表;2、对应的线程池状态不同;3、前者会保留正在执行及未执行的任务继续执行,后者是将所有线程全部关闭
考点2:当shutDown停止线程池,对于后面这行完毕的线程是如何进行处理的?在getTask()中,有根据线程池的状态且任务队列为空的时候,会返回null对象,而不是继续等待,这样当前线程就结束了

	private Runnable getTask() {
        boolean timedOut = false; // Did the last poll() time out?

        for (;;) {
            int c = ctl.get();
            int rs = runStateOf(c);

            // 在这个特定的场景下,判断任务队列是否为null,来结束当前线程
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                decrementWorkerCount();
                return null;
            }

            ...
    }

拒绝策略

  • AbortPolicy:当队列无法添加时,直接抛异常
    	public static class AbortPolicy implements RejectedExecutionHandler {
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                throw new RejectedExecutionException("Task " + r.toString() +
                                                     " rejected from " +
                                                     e.toString());
            }
        }
    
  • DiscardPolicy:当队列无法添加任务时,啥也不处理
    	public static class DiscardPolicy implements RejectedExecutionHandler {
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
            }
    	}
    
  • DiscardOlderPolicy:当队列无法添加任务时,如果线程池未关闭状态,则会移除队列头部的任务,然后将新任务添加进去
    	public static class DiscardOldestPolicy implements RejectedExecutionHandler {
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                if (!e.isShutdown()) {
                    e.getQueue().poll();
                    e.execute(r);
                }
            }
        }
    
  • CallerRunsPolicy:当队列无法添加任务时,如果线程池未关闭状态,直接在调用线程池的线程中运行runnable;风险点:需要注意的是,可能会在主线程中执行耗时任务
    	public static class CallerRunsPolicy implements RejectedExecutionHandler {
            public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {
                if (!e.isShutdown()) {
                    r.run();
                }
            }
        }
    
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值