阿里一面:那我把线程池coreSize配置成0会怎样?

打印 上一主题 下一主题

主题 915|帖子 915|积分 2749

写在前面

假如我的项目中有一个非常不重要的链路,偶尔需要执行一下。在线程池设计的时间,我想到了线程池的八股文。于是为了尽大概节约资源,于是我把“常驻”的焦点线程数配置成了0,这样的线程池能执行使命吗?
线程池八股文回顾

使命投递时,有以下几种计谋:

  • 线程池线程数量 < 焦点线程数,则创建一个新的线程执行使命
  • 线程池线程数量 >= 焦点线程数
    ** 阻塞队列未满:投递使命进阻塞队列中
    ** 阻塞队列已满
    *** 线程池线程数量 < 最大线程数:创建新的线程执行当前使命
    *** 线程池线程数量 >= 最大线程数:执行拒绝计谋
大概得流程就是如上了,那corePoolSize == 0 的时间,按照上面的八股文,难道会直接投递进阻塞队列中等待执行吗?如果队列够大,会不会使命一直无法执行(因为队列没满,一直也不会创建“空闲线程”)
举个栗子

靠猜是没有用的,我们实践出真知。 下面我配置了一个线程池,期望投递使命的时间,能够通过“空闲线程”短时间帮忙处理,终极自行销毁掉,不持续占用系统资源。 那这种线程池在执行过程中有大概因为阻塞队列未满,终极使命迟迟没有执行吗?
  1. private static final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(  
  2. 0,  
  3. 8,  
  4. 5, TimeUnit.MINUTES,  
  5. new LinkedBlockingQueue<>(512),  
  6. new CallerRunsPolicy()  
  7. );
复制代码
这里使用这个线程池打印一个字符串,看看是否能够执行就好了
  1. public static void main(String[] args) {  
  2. MonitorThreadPoolConfig.addThreadPoolExecutor(threadPoolExecutor);  
  3.   
  4. threadPoolExecutor.execute(() -> System.out.println("hahahhaha "));  
  5. }
复制代码
通过执行结果可以得知:使命是会被执行的(这里我加了对线程池的定时埋点监控)

探寻源码
  1. public void execute(Runnable command) {  
  2. if (command == null)  
  3. throw new NullPointerException();  
  4. /*  
  5. * Proceed in 3 steps:  
  6. *  
  7. * 1. If fewer than corePoolSize threads are running, try to  
  8. * start a new thread with the given command as its first  
  9. * task. The call to addWorker atomically checks runState and  
  10. * workerCount, and so prevents false alarms that would add  
  11. * threads when it shouldn't, by returning false.  
  12. *  
  13. * 2. If a task can be successfully queued, then we still need  
  14. * to double-check whether we should have added a thread  
  15. * (because existing ones died since last checking) or that  
  16. * the pool shut down since entry into this method. So we  
  17. * recheck state and if necessary roll back the enqueuing if  
  18. * stopped, or start a new thread if there are none.  
  19. *  
  20. * 3. If we cannot queue task, then we try to add a new  
  21. * thread. If it fails, we know we are shut down or saturated  
  22. * and so reject the task.  
  23. */  
  24. int c = ctl.get();  
  25. if (workerCountOf(c) < corePoolSize) {  
  26. if (addWorker(command, true))  
  27. return;  
  28. c = ctl.get();  
  29. if (isRunning(c) && workQueue.offer(command)) {  
  30. int recheck = ctl.get();  
  31. if (! isRunning(recheck) && remove(command))  
  32. reject(command);  
  33. else if (workerCountOf(recheck) == 0)  
  34. addWorker(null, false);  
  35. }  
  36. else if (!addWorker(command, false))  
  37. reject(command);  
  38. }
复制代码
其实这个问题也不复杂,从粘贴出来的第34行 - 第35行可以看出:当焦点线程数 == 0的时间会创建一个新的线程执行当前的使命
拓展一下

既然可以通过corePoolSize == 0的方式来尽大概淘汰”常驻“线程的资源占用,那有没有别的办法可以达到同样的结果呢?
八股文战神大概会抢答了:ThreadPoolExecutor自1.6开始有一个属性如下,它的作用是支持焦点线程超时销毁
  1. /**  
  2. * If false (default), core threads stay alive even when idle.  
  3. * If true, core threads use keepAliveTime to time out waiting  
  4. * for work.  
  5. */  
  6. private volatile boolean allowCoreThreadTimeOut;
复制代码
于是我们可以将线程池配置改成如下再试一下(留意我把超时时间改成了5秒钟):
  1. private static final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(  
  2. 1,  
  3. 8,  
  4. 5, TimeUnit.SECONDS,  
  5. new LinkedBlockingQueue<>(512),  
  6. new CallerRunsPolicy()  
  7. );  
  8.   
  9. public static void main(String[] args) {  
  10. MonitorThreadPoolConfig.addThreadPoolExecutor(threadPoolExecutor);  
  11. threadPoolExecutor.allowCoreThreadTimeOut(true);  //核心线程数可以超时
  12.   
  13. threadPoolExecutor.execute(() -> System.out.println("hahahhaha "));  
  14. }
复制代码
执行结果如下,符合我们的预期。可以看到使命正常执行、线程池的线程数量初始是0,随后是1,末了天然销毁了,酿成了0。

总结


  • 当焦点线程数设置为0的时间,在使命投递后,线程池内部会创建一个新的线程来执行使命(固然你的最大线程数配置要大于0)
  • 针对功能点执行频率极低的场景,我们可以使用文中形貌的两种方式(1. 焦点线程数为零 2.
  • naallowCoreThreadTimeOut == true)来让线程池临时创建可超时销毁的线程来执行使命
ps:据说JDK1.6之前corePoolSize == 0的话,线程池真的大概会出现投递进阻塞队列后没有线程执行的尴尬。

免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!更多信息从访问主页:qidao123.com:ToB企服之家,中国第一个企服评测及商务社交产业平台。

本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?立即注册

x
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

王國慶

金牌会员
这个人很懒什么都没写!

标签云

快速回复 返回顶部 返回列表