ThreadPoolExecutor 理解

  参数的理解:
核心和最大池大小  Core and maximum pool sizes
ThreadPoolExecutor将根据corePoolSize 和 maximumPoolSize 设置的边界自动调整线程池大小,在方法execute(Runnable)中提交新任务时,如果运行的线程数少于corePoolSize, 即使其他工作线程处于空闲状态,也会创建一个新线程来处理请求。 如果运行的线程数少于最大池大小,并且在队列已满时 则将创建一个新线程处理请求。通过将corePoolSize和maximumPoolSize设置为相同值,可以创建一个固定大小的线程池。 通过将 maximumPoolSize 设置为基本上无界的值,如Integer.MAX_VALUE 就是允许线程池容纳任意数量的并发任务。核心和最大池大小可以在构建时设置,也可以使用setCorePoolSize 和 setMaximumPoolSize 动态更改。

  // 对于 corePoolSize (核心线程数 来说)

  if (池中已经创建的线程 <  corePoolSize){

                   立即创建一个线程来处理请求。

    } 

 // 对于 maximumPoolSize (最大池中线程数大小 来说)

 if ( (运行的线程数 <  maximumPoolSize )  &&  workQueue.isEmpty()){

                  立即创建一个线程来处理请求。

   }

corePoolSize:池中要保留的线程数,即使它们处于空闲状态。
maximumPoolSize:池中允许的最大线程数
keepAliveTime:当线程数大于核心时,这是多余空闲线程在终止前等待新任务的最长时间。
unit:keepAliveTime参数的时间单位
workQueue:在执行任务之前用于保存任务的队列。此队列将仅保存execute方法提交的Runnable任务。
threadFactory:执行器创建新的线程时使用的工厂
拒绝策略:当执行因达到线程边界 和 队列容量时 使用的策略,如果任务阻塞队列已满且线程池中的线程数等于maximumPoolSize,说明线程池此时处于饱和状态,应该执行一种拒绝策略来处理新提交的任务。

 4种拒绝策略:

  1.默认的拒绝策略  new ThreadPoolExecutor.AbortPolicy();

      直接抛出异常:抛出RejectedExecutionException

  2.由提交任务的线程处理该任务: new ThreadPoolExecutor.CallerRunsPolicy();

     public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {

          if (!e.isShutdown()) {

                r.run();

          }

      }

 3.不执行任务,也不抛出异常,直接丢弃:new ThreadPoolExecutor.DiscardPolicy()

    方法里面什么也没有实现:

     public void rejectedExecution(Runnable r, ThreadPoolExecutor e) { }

 4.丢弃队列中最老的任务,然后尝试再次提交任务:

     new ThreadPoolExecutor.DiscardOldestPolicy()

     方法的实现:

      public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {

              if (!e.isShutdown()) {

                    e.getQueue().poll();

                     e.execute(r);

               }

        }

 5. 自定义拒绝策略 实现 RejectedExecutionHandler 接口中的 rejectedExecution 方法

   void rejectedExecution(Runnable r, ThreadPoolExecutor executor); 

execute方法的流程:
public static void main(String[] args) {
        // 创建一个固定大小的线程池
        BlockingQueue<Runnable> workQueue = new LinkedBlockingQueue<>();
        ThreadPoolExecutor executor = new ThreadPoolExecutor(
                1, // 核心线程数
                2, // 最大线程数
                0L, // 存活时间
                TimeUnit.MILLISECONDS,
                workQueue,
                new ThreadPoolExecutor.CallerRunsPolicy() // 拒绝策略
        );

        // 提交任务
        for (int i = 0; i < 10; i++) {
            executor.execute(() -> {
                System.out.println("Task executed on thread: " + Thread.currentThread().getName());
            });
        }
        // 关闭线程池
        executor.shutdown();

    }
用的是默认的线程工厂
Executors.defaultThreadFactory()

线程池的控制状态ctl是一个原子整数,它包含了两个概念字段 workerCount:表示线程的有效数量
runState:表示是否正在运行、关闭等
private final AtomicInteger  ctl = new AtomicInteger(ctlOf(RUNNING, 0));
private static int ctlOf(int rs, int wc) { return rs | wc; }
//workerCount 线程的数量(2^29)-1(约5亿)个线程
private static final int COUNT_BITS = Integer.SIZE - 3;
private static final int COUNT_MASK = (1 << COUNT_BITS) - 1; 

COUNT_MASK 二进制是:00011111111111111111111111111111
COUNT_MASK 值是:536870911


// runState 存储在高位
private static final int RUNNING    = -1 << COUNT_BITS;
    -1 的二进制数:11111111111111111111111111111111
左移动29的二进制数:11100000000000000000000000000000 
RUNNIN 的   值是: -536870912  
中间记录一下负数 左移动的 插曲:   
负数:取最高位有值的数,中间有间隔的数 减去间隔的数字。取反
例如:-10
源码:0000 1010
反码:1111 0101
补码:1111 0110
左移动4位 -10 int 类型的二进制:1111 1111 1111 1111 1111 1111 0110 0000
取最高位的值是:从右边数第9位是:256 减去间隔的值右边数6位和7位,他们的值是 64+32=96
 256 - 96 = 160
private static final int SHUTDOWN   =  0 << COUNT_BITS;
     0 的二进制数:0
左移动29的二进制数:0
SHUTDOWN 的 值是:0
private static final int STOP       =  1 << COUNT_BITS;
     1 的二进制数:00000000000000000000000000000001
左移动29的二进制数:00100000000000000000000000000000
STOP     的 值是:536870912
private static final int TIDYING    =  2 << COUNT_BITS;
     2 的二进制数:00000000000000000000000000000010
左移动29的二进制数:01000000000000000000000000000000
TIDYING  的 值是:1073741824
private static final int TERMINATED =  3 << COUNT_BITS;
     3 的二进制数:00000000000000000000000000000011
左移动29的二进制数:01100000000000000000000000000000
TERMINATED的值是:

进入 execute 方法:

 public void execute(Runnable command) {
        if (command == null)
            throw new NullPointerException();
        /**
         * 分为3个步骤:
         *
         *    1.如果运行的线程数少于corePoolSize,请尝试使用给定的任务作为第一个任务启动一个新线程。
         *    对addWorker的调用会自动检查runState和workerCount,
         *    从而通过返回false来防止在不应该添加线程的情况下添加错误警报
         *
         *    2.如果一个任务可以成功排队,那么我们仍然需要仔细检查是否应该添加一个线程(因为自上次检查以来,现有的线程已经死亡),
         *    或者池是否在进入此方法后关闭。因此,我们重新检查状态,并在必要时回滚查询,如果没有,则停止或启动新线程。
         *
         *     3.如果我们无法对任务进行排队,那么我们会尝试添加一个新线程。
         *       如果它失败了,我们知道我们被关闭或饱和了,因此拒绝了这项任务。
         *
         */
        /**
         * 第一次进来
         *    ctl.get() 获取的值是 -536870912
         *    初始化的时候 RUNNING 是 :11100000000000000000000000000000
         *    private final AtomicInteger  ctl = new AtomicInteger(ctlOf(RUNNING, 0));
         *    经过 | 后 结果不变
         *    private static int ctlOf(int rs, int wc) { return rs | wc; }
         * 第二次进来
         *   ctl.get() 获取的值是 -536870911  (在第一次的时候已经 进行了 + 1)
         */
        int c = ctl.get();
        /**
         * 第一次进来
         *    private static int workerCountOf(int c)  { return c & COUNT_MASK; }
         *    c 传过来的值是 -536870912 & COUNT_MASK
         *    COUNT_MASK 的值是:536870911
         *    c的二进制数:  11100000000000000000000000000000
         *               &
         *    COUNT_MASK: 00011111111111111111111111111111
         *    是 0   corePoolSize 是 1  结果是 true
         * 第二次进来
         *    private static int workerCountOf(int c)  { return c & COUNT_MASK; }
         *    c 传过来的值是 -536870911 & COUNT_MASK
         *    COUNT_MASK 的值是:536870911
         *    c的二进制数:  11100000000000000000000000000001
         *               &
         *    COUNT_MASK: 00011111111111111111111111111111
         *    是 1   corePoolSize 是 1  结果是 false
         */
        if (workerCountOf(c) < corePoolSize) {

            if (addWorker(command, true))
                return;
            c = ctl.get();
        }
        // 因为我核心数的大小设置的是 1 ,所以第二次就进到这里
        // private static boolean isRunning(int c) { return c < SHUTDOWN; }
        // c 是 -536870911  <  SHUTDOWN 是 0 结果是true
        // 然后判断队列是否可以插入数据  workQueue.offer(command) 没有给队列设置大小,可以插入进来
        if (isRunning(c) && workQueue.offer(command)) {
            int recheck = ctl.get();
            // 上面已经验证, 这里取反返回false
            if (! isRunning(recheck) && remove(command))
                reject(command);
                // private static int workerCountOf(int c)  { return c & COUNT_MASK; }
                // COUNT_MASK的二进制是:    11111111111111111111111111111
                //  c的二进制是:         11100000000000000000000000000001
                //  返回 1 结果为 false   里面没有处理任务 直接返回了 , 全部添加到了队列
            else if (workerCountOf(recheck) == 0)
                addWorker(null, false);
        }
        //将 队列设置为1 后 直接走到拒绝策略
        else if (!addWorker(command, false))
            reject(command);
    }
addWorker(Runnable firstTask, boolean core)方法:
/**
     * 检查是否可以根据当前线程池状态和给定的绑定(核心或最大值)添加新的worker。
     * 如果可以,则创建并启动一个新worker,将firstTask作为其第一个任务运行。
     * 如果线程池已停止或符合关闭条件,则此方法返回false。如果线程工厂在被询问时不能创建线程,它也会返回false。
     * 如果线程创建失败,无论是由于线程工厂返回null,还是由于异常(通常是thread.start()中的OutOfMemoryError),
     * 我们都会彻底回滚。
     * @param firstTask 线程
     * @param core true 当前的线程数 < core线程数
     * @return
     */

    private boolean addWorker(Runnable firstTask, boolean core) {
        retry:
        // c 是  -536870912
        for (int c = ctl.get();;) {
            //  运行状态的检查
            //  private static boolean runStateAtLeast(int c, int s) { return c >= s; }
            //
            //  private static final int SHUTDOWN   =  0 << COUNT_BITS;
            //  private static final int STOP       =  1 << COUNT_BITS;
            //  SHUTDOWN 是 0  STOP 是 536870912
            //  -536870912 >= 0 && -536870912 > 536870912 返回 false
            if (runStateAtLeast(c, SHUTDOWN)
                    && (runStateAtLeast(c, STOP)
                    || firstTask != null
                    || workQueue.isEmpty()))
                return false;

            for (;;) {
                // private static int workerCountOf(int c)  { return c & COUNT_MASK; }
                // c 的 二进制是: 11100000000000000000000000000000
                // COUNT_MASK是: 00011111111111111111111111111111
                // 没有线程在工作 返回 0
                // 0 >= 1
                if (workerCountOf(c)
                        >= ((core ? corePoolSize : maximumPoolSize) & COUNT_MASK))
                    return false;
                if (compareAndIncrementWorkerCount(c))
                    break retry;
                c = ctl.get();  // Re-read ctl
                if (runStateAtLeast(c, SHUTDOWN))
                    continue retry;
                // else CAS failed due to workerCount change; retry inner loop
            }
        }

        boolean workerStarted = false;
        boolean workerAdded = false;
        ThreadPoolExecutor.Worker w = null;
        try {
            //利用线程的工厂创建线程
            w = new ThreadPoolExecutor.Worker(firstTask);
            final Thread t = w.thread;
            if (t != null) {
                // 上锁
                final ReentrantLock mainLock = this.mainLock;
                mainLock.lock();
                try {
                    // 拿到锁后重新检查。
                    // 如果ThreadFactory失败或在获得锁之前关闭,则退出。
                    // 前边已经原子 进行了 加 1  获取的值是:-536870911
                    int c = ctl.get();

                    // private static boolean isRunning(int c) { return c < SHUTDOWN;  }
                    //  SHUTDOWN 是 0
                    //  结果返回true
                    if (isRunning(c) ||
                            (runStateLessThan(c, STOP) && firstTask == null)) {
                        // 新创建的线程 没有执行之前的状态都是 new
                        if (t.getState() != Thread.State.NEW)
                            throw new IllegalThreadStateException();
                        workers.add(w);
                        workerAdded = true;
                        int s = workers.size();
                        // 跟踪已达到的最大池大小。仅在mainLock下访问
                        if (s > largestPoolSize)
                            largestPoolSize = s;
                    }
                } finally {
                    mainLock.unlock();
                }
                if (workerAdded) {
                    t.start();
                    workerStarted = true;
                }
            }
        } finally {
            if (! workerStarted)
                addWorkerFailed(w);
        }
        return workerStarted;
    }

辅助方法:

// 原子修改 这个 线程池状态 工作线程 +1
    private boolean compareAndIncrementWorkerCount(int expect) {
        return ctl.compareAndSet(expect, expect + 1);
    }

    //创建一个线程
    Worker(Runnable firstTask) {
        setState(-1); // inhibit interrupts until runWorker
        this.firstTask = firstTask;
        this.thread = getThreadFactory().newThread(this);
    }

根据拒绝的策略,最后由main方法 执行拒绝后的任务 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值