• 并发编程之ThreadPoolExecutor源码解析


    本节解析要点如下:

    1、线程池的执行原理

    2、线程是如何复用的

    3、核心线程数如何一直保持、最大线程数如何释放

    4、线上环境线程池应该定义多大

    一 线程池初始化原理

    可参考博客:https://www.jianshu.com/p/23cb8b903d2c

     1 public void execute(Runnable command) {
     2          //如果提交的任务为null  抛出空指针异常*/
     3         if (command == null)
     4             throw new NullPointerException();
     5            
     6         int c = ctl.get();
     7         //如果当前的任务数小于等于设置的核心线程大小,那么调用addWorker直接执行该任务*/
     8         if (workerCountOf(c) < corePoolSize) {
     9             if (addWorker(command, true))
    10                 return;
    11             c = ctl.get();
    12         }
    13         //如果当前的任务数大于设置的核心线程大小,而且当前的线程池状态时运行状态,那么向阻塞队列中添加任务*/
    14         if (isRunning(c) && workQueue.offer(command)) {
    15             int recheck = ctl.get();
    16             if (! isRunning(recheck) && remove(command))
    17                 reject(command);
    18             else if (workerCountOf(recheck) == 0)
    19                 addWorker(null, false);
    20         }
    21         //如果向队列中添加失败,那么就新开启一个线程来执行该任务
    22         else if (!addWorker(command, false))
    23             reject(command);
    24 }
    View Code

    核心要点如下:

    addWorker(Runnable firstTask, boolean core)->w = new Worker(firstTask)->t.start()->runWorker(Worker w)->getTask()->task.run()->addWorker(null, false)

    二 线程如何复用

    请看runWorker方法:runWorker方法里有两个重要方法:getTask() 和 processWorkerExit(w, completedAbruptly)

    线程执行完毕后,会在finally方法里执行processWorkerExit(w, completedAbruptly)方法,此方法会把当前线程重新添加到worker队列,所以线程可以复用

    源码分析如下:

    1、如果当前线程未超过核心线程数,则task不为空,直接执行task.run()方法:具体请看execute和processWorkerExit方法里的区别:

    三 核心线程如何一直保持,最大线程数如何释放

    请关注runWorker方法里有个getTask()方法:

    1、当前线程数小于核心线程数时:timed为false,当前线程一直阻塞,所以核心线程可以一直保持,知道等待有请求加入队列才唤醒执行

    2、当前线程数大于核心线程数:timed为true,workQueue.poll()超时后,进入下次循环,直接return退款while,当前线程释放,即最大线程释放

    四 线上线程池大小如何设置

    1、IO密集型: 最佳线程数目 = ((线程等待时间+线程CPU时间)/线程CPU时间 )* CPU数目

    2、CPU密集型:最佳线程数目 =CPU数目+1

    可以得出一个结论: 
    线程等待时间所占比例越高,需要越多线程。线程CPU时间所占比例越高,需要越少线程。 

  • 相关阅读:
    springcloud 使用feign
    Could not resolve placeholder ‘xxx‘ in value “${xxx}“
    小程序中腾讯位置服务的使用/小程序中使用腾讯服务获取位置信息
    h5页面节假日置灰
    form表单提交入参唤起支付
    小程序中下拉框组件
    Android实践项目汇报(四)
    WORD表格数据运算技巧
    路由器桥接(WIFI无线中继)设置及摆放位置图解
    批处理设置IP地址
  • 原文地址:https://www.cnblogs.com/housh/p/13069761.html
Copyright © 2020-2023  润新知