源码解析线程池的执行流程

在阅读此文章之前,应先了解线程池的基本知识,详情可以看我上一篇博客:初识线程池

一、执行流程图

在这里插入图片描述
任务被提交到线程池,会先判断当前线程数量是否小于corePoolSize,如果小于则创建线程来执行提交的任务,否则将任务放入workQueue队列,如果workQueue满了,则判断当前线程数量是否小于maximumPoolSize,如果小于则创建线程执行任务,否则就会调用handler拒绝策略,以表示线程池拒绝接收任务
在这里插入图片描述

二、源码解析 (jdk1.7)

下来看一下,上述的流程在源码中是如何体现的,ThreadPoolExecutor类中的内容在上一个博客中已经解释,下面直接开始上代码:

用户提交线程的方式有两种:submit()和execute()。

  • submit()方法主要是继承了AbstractExecutorService类中的三个方法,从源码很清晰的可以看到这个方法是含有返回值的,而且三种方法的参数列表都不一样,Runnable和Callable两种任务类型(两种类型的区别?)。而且每个submit方法内部最终都调用了execute()方法
    public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        execute(ftask);
        return ftask;
    }
    
    public <T> Future<T> submit(Runnable task, T result) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task, result);
        execute(ftask);
        return ftask;
    }
    
    public <T> Future<T> submit(Callable<T> task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<T> ftask = newTaskFor(task);
        execute(ftask);
        return ftask;
    }
  • execute()方法。既然上面说了,submit方法最终都调用了这个方法,那么这个方法应该就是线程池提交流程中最基础的方法。
public void execute(Runnable command) {
       //相当于参数校验,判断当前的任务是否为空
        if (command == null)
            throw new NullPointerException();
                
       //获得当前任务的状态   
        int c = ctl.get();
		//如果当前工作的线程数<corePoolSize核心线程数
        if (workerCountOf(c) < corePoolSize) {
			//调用addWorker创建线程,执行任务
			if (addWorker(command, true))
                return;
		//创建线程失败:①线程池处于running之后的状态②超出核心或者最大线程数
            c = ctl.get();  //再次获取
        }  
		//如果当前工作的线程数>corePoolSize
		//线程池处于Running状态,并且将任务添加到workQueue队列。
        if (isRunning(c) && workQueue.offer(command)) {
            //重新获取一次线程池的状态
            int recheck = ctl.get();
            //如果当前状态是非运行状态,则删除当前任务
            if (! isRunning(recheck) && remove(command))
               //执行拒绝策略,不在接受新的任务提交
			   reject(command);
			//如果还处于running状态,并且工作线程数为0
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);//创建新的线程
        }
		//如果放入workQueue失败,则创建线程执行任务,
		//如果这时创建线程失败(当前线程数>maximumPoolSize时),
		//就会调用reject拒绝策略(内部调用handler)拒绝接受任务
        else if (!addWorker(command, false))
            reject(command);
    }
  • addWorker()方法
 private boolean addWorker(Runnable firstTask, boolean core) {
        retry:  //重复尝试
		//外层for循环检查状态
        for (;;) {  
            int c = ctl.get(); //获得当前的状态表示的整型数
            int rs = runStateOf(c);  //通过整型数获得当前线程状态

            // Check if queue empty only if necessary.
            //如果线程池已关闭 并满足,不创建新的worker
			if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false; //添加失败

          //内层for循环检查数量
            for (;;) {
                int wc = workerCountOf(c);
			    //创建失败:wc>core时和核心数比较,否则和最大线程数比较
			    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;
                // else CAS failed due to workerCount change; retry inner loop
            }
        }
        boolean workerStarted = false;  //worker是否启动
        boolean workerAdded = false;   //是否添加成功
        Worker w = null;
        try {
            final ReentrantLock mainLock = this.mainLock; //定义一个可重入锁
            w = new Worker(firstTask);  //创建Worker对象,将firstTask传给它
            final Thread t = w.thread;//实例化一个Thread对象
            if (t != null) {
                mainLock.lock();//加锁
                try {
                    // Recheck while holding lock.
                    // Back out on ThreadFactory failure or if
                    // shut down before lock acquired.
                    int c = ctl.get();
                    int rs = runStateOf(c);
                    
                    //rs处于Running状态,(rs是shutdown状态并且firstTask为空)
                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {
                        if (t.isAlive()) // precheck that t is startable
                            throw new IllegalThreadStateException();
                       //将当前的线程加入到工作的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;
    }

  • addWorkerFailed()方法
 private void addWorkerFailed(Worker w) {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            if (w != null)  //如果当前工作为空,说明启动线程失败
                workers.remove(w); // 直接删掉这个工作
            decrementWorkerCount();  //workerCount-1
            tryTerminate();
        } finally {
            mainLock.unlock();
        }
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值