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

写在前面

设想一下,在我们的项目中存在一个边缘的业务流程,它并不频繁地被触发。在设计线程池时,我回想起了线程池的常见配置原则。为了最大限度地节省资源,我将核心线程数(corePoolSize)设置为0。这样的配置是否能够顺利执行任务呢?

线程池配置原则回顾

在任务提交时,线程池会根据以下策略进行处理:

  • 如果线程池中的线程数少于核心线程数,则创建一个新线程来执行任务。
  • 如果线程池中的线程数大于等于核心线程数:
  • 如果阻塞队列未满,则将任务放入阻塞队列中。
  • 如果阻塞队列已满:
    • 如果线程池中的线程数小于最大线程数,则创建一个新线程来执行当前任务。
    • 如果线程池中的线程数大于等于最大线程数,则执行拒绝策略。

基于上述流程,当corePoolSize设置为0时,任务是否会直接进入阻塞队列等待执行?如果队列足够大,任务是否可能因为队列未满而永远无法执行(因为没有空闲线程被创建)?

实践出真知

猜测无益,实践才是检验真理的唯一标准。下面我配置了一个线程池,希望在提交任务时,能够通过“空闲线程”快速处理任务,然后自动销毁,不占用系统资源。那么,这种配置的线程池是否可能因为阻塞队列未满而导致任务迟迟不被执行?

private static final ThreadPoolExecutor threadPoolExecutor = new ThreadPoolExecutor(  
    0,  
    8,  
    5, TimeUnit.MINUTES,  
    new LinkedBlockingQueue<>(512),  
    new CallerRunsPolicy()  
);

我们使用这个线程池来打印一个字符串,以验证任务是否能够被执行。

public static void main(String[] args) {  
    MonitorThreadPoolConfig.addThreadPoolExecutor(threadPoolExecutor);  

    threadPoolExecutor.execute(() -> System.out.println("hahahhaha "));  
}

执行结果显示:任务确实被执行了(这里我添加了对线程池的定时监控)。

执行结果

深入源码

public void execute(Runnable command) {  
    if (command == null)  
        throw new NullPointerException();  
    /*  
    * 执行分为三个步骤:  
    *  
    * 1. 如果运行的线程数少于核心线程数,尝试  
    * 用给定的命令作为其第一个任务启动一个新线程。  
    * addWorker原子检查runState和workerCount,  
    * 因此可以防止在不应该添加线程时添加线程。  
    *  
    * 2. 如果任务可以成功入队,那么我们仍然需要  
    * 再次检查是否应该添加一个线程(因为现有的线程可能已经死亡)  
    * 或者池是否已经关闭。因此,如果停止了,我们需要回滚入队操作,  
    * 或者如果没有线程,就启动一个新线程。  
    *  
    * 3. 如果我们不能将任务入队,那么我们尝试添加一个新线程。  
    * 如果失败,我们知道我们已经关闭或者饱和了,  
    * 因此拒绝任务。  
    */  
    int c = ctl.get();  
    if (workerCountOf(c) < corePoolSize) {  
        if (addWorker(command, true))  
            return;  
        c = ctl.get();  
        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);  
    }
}

从源码的第34行到第35行可以看出:当核心线程数为0时,会创建一个新的线程来执行当前任务。

进一步探讨

既然可以通过设置corePoolSize为0来最小化“常驻”线程的资源占用,那么是否有其他方法可以达到相同的效果呢?

有经验的开发者可能会立刻回答:从Java 1.6开始,ThreadPoolExecutor有一个属性可以实现核心线程超时销毁的功能。

/**  
* 如果设置为false(默认),即使空闲,核心线程也会保持活动状态。  
* 如果设置为true,核心线程将使用keepAliveTime来超时等待工作。  
*/  
private volatile boolean allowCoreThreadTimeOut;

我们可以将线程池配置如下

文章整理自互联网,只做测试使用。发布者:Lomu,转转请注明出处:https://www.it1024doc.com/4405.html

(0)
LomuLomu
上一篇 2024 年 12 月 26 日 上午4:21
下一篇 2024 年 12 月 26 日 上午5:22

相关推荐

  • 表的创建与删除:从理论到实践的全面指南

    title: 表的创建与删除:从理论到实践的全面指南date: 2025/1/1updated: 2025/1/1author: cmdragon excerpt:表是关系数据库的基本存储结构,承载着核心数据及其关联关系。在数据库设计与管理中,表的创建与删除是至关重要的操作,它直接影响数据库的结构、数据的完整性以及查询的性能。 categories: 前端开…

    2025 年 1 月 6 日
    45200
  • 双非二本,毕业一年多培训无果,拿到大厂 Offer

    大家好,我是R哥。 今天给大家分享一个逆袭的真实故事,本文的主人公小明(化名),小明是一名 2023 届往届生 ,毕业后因为种种原因,整整空档了一年多 。 小明的情况让我看了不禁感叹:“唉,这兄弟怎么搞啊的?这么年轻就躺平了? ”,毕竟,大家都知道,互联网行业的就业压力一年比一年大,稍微掉队,就可能被甩在后头,更别说还没就业就有这么长的空窗期。 然后,他选择…

    2025 年 1 月 16 日
    50300
  • Java 技术前沿:大数据在智能医疗远程手术中的创新应用(215)

    ✨亲爱的技术爱好者们,诚挚欢迎您访问【青云科技博客】!在这个充满机遇的数字时代,我们致力于打造一个专业的技术交流平台。这里汇聚了前沿技术资讯和实用开发技巧,期待与您共同探讨技术奥秘,携手迈向智能未来!✨全网平台(微信公众号/CSDN/抖音/华为/支付宝/微博):青云科技一、加入【技术精英社群】快速加入通道1:[青云技术精英社群(最新)]快速加入通道2:[CS…

    2025 年 5 月 19 日
    64600
  • JavaScript 延迟加载的方法( 7种 )

    JavaScript脚本的延迟加载(也称为懒加载)是指在网页的主要内容已经加载并显示给用户之后,再加载或执行额外的JavaScript代码。这样做可以加快页面的初始加载速度,改善用户体验,并减少服务器的压力。 以下是几种常见的延迟加载JavaScript的方法: defer 属性: 使用 async 属性: async 属性告诉浏览器立即开始下载脚本,并且在…

    2025 年 1 月 19 日
    50000
  • 【JavaSE】【网络协议】HTTP 请求和响应

    一、HTTP请求 1.1 请求格式 请求格式:首行+请求头(header)+空行+正文(body) 1.2 首行组成 首行组成:请求方法+URL+版本号。使用“空格”将他们分隔开。 1.2.1 请求方法 方法 说明 支持的HTTP版本 GET 获取资源 1.0 1.1 POST 传输实体主体 1.0 1.1 PUT 传输文件 1.0 1.1 DELETE 删…

    2025 年 1 月 15 日
    50600

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信