java 线程池源码解析

    以上基于源码自己理解,有不对的地方忘各位赐教

  • jdk 线程池源码解析(基于jdk1.8)

  线程池状态

    RUNNING:线程池处于运行状态,可以正常提交任务。

   SHUTDOWN:不在接收新的任务,会把已运行的线程和队列里存在的线程运行完毕(调用ExecutorService.shutdown())

    STOP:不在接收新的任务,且不运行队里里的任务 ,现有已在运行的任务也尝试取消(调用ExecutorService.shutdownnow())

    TIDYING:队列里已为空,且没有再运行的任务,但线程池的钩子函数terminated()未执行或者未执行完

   TERMINATED:钩子函数terminated()已执行完

                                                                     图1-1

 

主要核心参数介绍

1.corePoolSize

解释:线程池最小核心数,如果低于此值,每提交一个任务都会创建一个线程

2.maximumPoolSize

解释:当核心数大于corePoolSize且小于maximumPoolSize 如果放工作队列的任务已满则利用线程工厂创建一个新的线程

3.keepAliveTime

解释:如果allowCoreThreadTimeOut 为false(默认为false),且核心数大于corePoolSize且空闲时间大于keepAliveTime 则进行回收

4.TimeUnit

5.workQueue

解释:存放work的队列

主要以下三个实现

无界队列

有界队列

SynchronousQueue(这个不算是个队列,他没有内存存放任务,只是把提交的任务转发给线程池里的线程)

6.ThreadFactory

解释:创建线程的工厂,每创建一个线程都会调用ThreadFactory.newThread

这个默认是创建一个非守护线程的,正常线程优先级的线程

 

7.RejectedExecutionHandler

解释:如果现场池coresize数量等于maximumPoolSize,且放置任务的队列已满

则提交任务会有执行拒绝策略。jdk提空了如下策略

ThreadPoolExecutor.AbortPolicy(抛出RejectedExecutionException)

ThreadPoolExecutor.CallerRunsPolicy(直接在主线程执行,阻塞客户端)

ThreadPoolExecutor.DiscardPolicy(直接抛弃,但是不抛异常)

ThreadPoolExecutor.DiscardOldestPolicy(置换最老的任务)

如果以上不符合需求可以实现RejectedExecutionHandler 接口

源码解析

一.类结构分析

1. ThreadPoolExecutor extends AbstractExecutorService

2. AbstractExecutorService implements ExecutorService

3.interface ExecutorService extends Executor 

Executor: 只有一个方法(此接口标志这个是个任务执行框架)

ExecutorService :此接口增加了线程生命周期的管理

AbstractExecutorService  (骨架实现类主要是对接口的一些默认实现)

ThreadPoolExecutor(实现的一个线程池的执行服务,生命周期管理,线程创建)

二.任务执行流程

 

 

    

 

三.小技巧

ThreadPoolExecutor 利用一个int表示两个状态

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

正在运行的核心数

线程池的状态

一个int是32为,将其拆分为前3位和后29位

前三位表示线程池状态,后29位表示运行的核心数

即111(后29为表示正在运行的核心数)表示可运行,

即000(后29为表示正在运行的核心数)表示shutdown,

即001(后29为表示正在运行的核心数)表示STOP,

即010(后29为表示正在运行的核心数)表示TIDYING,

即011(后29为表示正在运行的核心数)表示TERMINATED,

即小于0表示可运行状态

四.threadPoolExecutor.execute源码解析

1.execute 方法

public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
      //存放实际运行核心数和线程池状态的原子变量
        int c = ctl.get();

    /**
     * 判断实际执行线程是否小于corePoolSize 如果小于 
     * 则执行addWorker(addWorker  创建新的线程执行任务)
     * 如果addwork执行成功则直接返回
     * 如果不成功则表示有其他任务并发的调用addWorker()
     * 走下面的逻辑(下面的逻辑后面分析)
     */
        if (workerCountOf(c) < corePoolSize) {
            if (addWorker(command, true))
                return;
            c = ctl.get();
        }

 

2.addwork分析

 private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        for (;;) {

            //获取存放状态变量和运行数量的原子变量
            int c = ctl.get();
            int rs = runStateOf(c);

             /**
      * 由前面的小技巧知道 >=SHUTDOWN 除了running为负数其他的状态都是大于等于SHUTDOWN
      *  ! (rs == SHUTDOWN &&
      *             firstTask == null &&
      *            ! workQueue.isEmpty())
      * 这个判断个人理解(我们知道线程池处于SHUTDOWN 状态,需要执行完所有的队列里的任务,
      * 如果这个队列比较大且我们想尽快执行完队列里的任务,我们可以适当增加核心数(setcoresize),
      * 然后调用prestartAllCoreThreads(会调用addWorker(null,true))产生更多的core,以便更快的消费队列里的任务)
      * 
      */
            if (rs >= SHUTDOWN &&
                ! (rs == SHUTDOWN &&
                   firstTask == null &&
                   ! workQueue.isEmpty()))
                return false;

 

            for (;;) {

               //获取活动线程数
                int wc = workerCountOf(c);

             /**
              * CAPACITY 活动线程的最大表示法(即int的后39为所能表示的最大值)
              * 如果有其他线程并发修改了此值是的core大于等于了corePoolSize则返回false
              * 
              */
                if (wc >= CAPACITY ||
                    wc >= (core ? corePoolSize : maximumPoolSize))
                    return false;

                //通过cas 修改实际运行的值如果修改成功则跳出循环
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                c = ctl.get();  

                //如果线程池状态改变跳到上一个循环重新执行
                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);

            //实际执行任务的线程
            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 如果线程池处于运行状态  (rs == SHUTDOWN && firstTask == null)) 这个是上面判断的反面

                    if (rs < SHUTDOWN ||
                        (rs == SHUTDOWN && firstTask == null)) {

                          // 判断线程是否或者
                        if (t.isAlive()) // precheck that t is startable
                            throw new IllegalThreadStateException();

                       //将活动线程放在维护的set中
                        workers.add(w);
                        int s = workers.size();

                      //  全局变量维护着最大的活动线程
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                        workerAdded = true;
                    }
                } finally {
                    mainLock.unlock();
                }
                if (workerAdded) {

                   //执行线程的start方法启动线程
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {

            //失败处理
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }

3.Worker线程类分析

  //构造函数 setState 表示线程已创建但未开始执行start

 Worker(Runnable firstTask) {
            setState(-1); // inhibit interrupts until runWorker
            this.firstTask = firstTask;
            this.thread = getThreadFactory().newThread(this);
        }

//进一步查看runWorker

 public void run() {
            runWorker(this);
        }

final void runWorker(Worker w) {

          //获取当前线程
        Thread wt = Thread.currentThread();
        Runnable task = w.firstTask;

        //保证线程消亡  线程对象被回收
        w.firstTask = null;
        w.unlock(); // allow interrupts
        boolean completedAbruptly = true;
        try {

            //循环从队列里获取任务getTask()后面分析
            while (task != null || (task = getTask()) != null) {
                w.lock();
             

             //  如果当前线程池状态大于等于stop 则保持线程处于中断状态

             //防止线程无线阻塞停止不了 合理的终止线程
                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);
        }
    }

 

4.getTask()   方法分析

 boolean timedOut = false; 

        for (;;) {

           // 存放线程池状态及核心说的变量
            int c = ctl.get();

         
            int rs = runStateOf(c);

            // Check if queue empty only if necessary.

            //如果线程池状态为大于shutdown 线程池队列为空,或者状态大于stop 则直接返回null 让线程结束
            if (rs >= SHUTDOWN && (rs >= STOP || workQueue.isEmpty())) {
                decrementWorkerCount();
                return null;
            }

           // 核心数

         int wc = workerCountOf(c);

            // 如果allowCoreThreadTimeOut  false(如果不想回收线程可以设置这个参数为true)  并且 活动线程数> corePoolSize

          // 说明需要进行回收
            boolean timed = allowCoreThreadTimeOut || wc > corePoolSize;

      //如果wc 大于最大线程数,或者线程空闲时间超时  (timedOut 为true)    并且队列为空 则返回null 回收线程

      if ((wc > maximumPoolSize || (timed && timedOut))
                && (wc > 1 || workQueue.isEmpty())) {
                if (compareAndDecrementWorkerCount(c))
                    return null;
                continue;
            }

            try {

              //在活越时间内如果从队里里拿不到线程则设置timedOut ,如果拿到则返回队列里的任务
                Runnable r = timed ?
                    workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :
                    workQueue.take();
                if (r != null)
                    return r;
                timedOut = true;
            } catch (InterruptedException retry) {
                timedOut = false;
            }
        }
    }

 

六.下面分析execute  后半段代码

 //如果线程池是running状态 则将线程放入线程队列   

  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);
        }

        //添加失败 拒绝策略
        else if (!addWorker(command, false))
            reject(command);

7.其他api的介绍

 public Future<?> submit(Runnable task) {
        if (task == null) throw new NullPointerException();
        RunnableFuture<Void> ftask = newTaskFor(task, null);
        execute(ftask);
        return ftask;
    }

这个方法也是走的execute 只是外围封装了一层

 public void shutdown() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            checkShutdownAccess();
            advanceRunState(SHUTDOWN);
            interruptIdleWorkers();
            onShutdown(); // hook for ScheduledThreadPoolExecutor
        } finally {
            mainLock.unlock();
        }
        tryTerminate();
    }

这个方法是修改线程状态,将空闲线程设置为中断状态,调用线程onShutdown 的回调函数,尝试进入Terminate

 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;
    }

 public int getActiveCount() {
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            int n = 0;
            for (Worker w : workers)
                if (w.isLocked())
                    ++n;
            return n;
        } finally {
            mainLock.unlock();
        }
    }

public boolean isLocked() { return isHeldExclusively(); }

        protected boolean isHeldExclusively() {
            return getState() != 0;
        }

这个获取已经创建但未调用start的线程

public int prestartAllCoreThreads() {
        int n = 0;
        while (addWorker(null, true))
            ++n;
        return n;
    }

初始化空线程到核心数(这个方法可以让线程池再没有获取任务时就初始化线程)

 public boolean awaitTermination(long timeout, TimeUnit unit)
        throws InterruptedException {
        long nanos = unit.toNanos(timeout);
        final ReentrantLock mainLock = this.mainLock;
        mainLock.lock();
        try {
            for (;;) {
                if (runStateAtLeast(ctl.get(), TERMINATED))
                    return true;
                if (nanos <= 0)
                    return false;
                nanos = termination.awaitNanos(nanos);
            }
        } finally {
            mainLock.unlock();
        }
    }

这个方法是等待线程池处于termination 在规定时间内(如果已经是termination 则直接返回true)

  public void purge() {
        final BlockingQueue<Runnable> q = workQueue;
        try {
            Iterator<Runnable> it = q.iterator();
            while (it.hasNext()) {
                Runnable r = it.next();
                if (r instanceof Future<?> && ((Future<?>)r).isCancelled())
                    it.remove();
            }
        } catch (ConcurrentModificationException fallThrough) {
            // Take slow path if we encounter interference during traversal.
            // Make copy for traversal and call remove for cancelled entries.
            // The slow path is more likely to be O(N*N).
            for (Object r : q.toArray())
                if (r instanceof Future<?> && ((Future<?>)r).isCancelled())
                    q.remove(r);
        }

        tryTerminate(); // In case SHUTDOWN and now empty
    }

尝试删除运行队列里的任务

 public boolean remove(Runnable task) {
        boolean removed = workQueue.remove(task);
        tryTerminate(); // In case SHUTDOWN and now empty
        return removed;
    }

尝试删除任务

其他的方法都是对现有参数的一些设置不列举了

.扩展

1.可以集成ThreadPoolExecutor 重写以下 方法(可以在每个任务执行之前和之后做一些日志记录)

beforeExecute() 每个任务执行之前调用的方法

afterExecute() 每个任务执行之后调用的方法

2.继承ThreadFactory 实现自己的线程工厂

jdk默认实现

public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r,
                                  namePrefix + threadNumber.getAndIncrement(),
                                  0);
            if (t.isDaemon())
                t.setDaemon(false);
            if (t.getPriority() != Thread.NORM_PRIORITY)
                t.setPriority(Thread.NORM_PRIORITY);
            return t;
        }

jdk默认是创建一个非守护线程,线程优先级为NORM_PRIORITY 的线程 默认组

我们可以重写newThread 给创建的线程起一个合理的名字方便查看,建立一些日志信息每创建一个线程时等

3.实现RejectedExecutionHandler 接口 建立自己的处理策略

 void rejectedExecution(Runnable r, ThreadPoolExecutor executor);

比如我们可以把不能 处理的任务广播给其他机器处理等

 

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值