Java 线程池(ThreadPoolExecutor)的自动调整策略分析

Java线程池(ThreadPoolExecutor)原理分析与使用 在我们的开发中“池”的概念并不罕见,有数据库连接池、线程池、对象池、常量池等等。下面我们主要针对线程池来一步一步揭开线程池的面纱。使用线程池的好处1、降低资源消耗 可以重复利用已创建的线程降低线程创建和销毁造成的消耗。 2、提高响应速度 当任务到达时,任务可以不需要等到线程创建就能立即执行。 3、提高线程的可管理性 线程是稀缺资源,如果无限制地创建,不仅会消耗系统资源,还会降低系统的稳定性 阅读详情

前言:
最近分析Java源码,对Java的线程池有一些疑惑,特提出来,希望大家能一起讨论确认一下。

  1. Java提供了线程池, ThreadPoolExecutor 实现,可以在 corePoolSize 和 maximumPoolSize 中自动根据传入的任务数自动调整。
  2. 注释中有这样一段话:
If there are more than corePoolSize but less than maximumPoolSize threads running, a new thread will be created only if the queue is full

3.个人觉得这个”is full” 的条件真的是 很傻的设计, 比较合理的设计应该是 “线程数根据提交的任务,自动在 corePoolSize 和 maximumPoolSize 中调整, 和队列是否满没有关系。这样才能够在任务压力低时降低负荷,在任务压力高时及时处理”。

考虑如下场景和需求:
一个服务器希望通过线程池进行服务,为了自动适应网络请求,希望根据请求的任务数自动调整线程数:
- 线程数:最低值为 CPU个数, 最高值为 CPU个数 x 2
- 队列任务数:为了不丢失请求,不设置队列上限

相信这种场景,应该是一个比较常见的需求,但 ThreadPoolExecutor 却无法满足?
当然,一般队列都会设置上限,避免出现内存等问题,不过设置的大的话; 线程无法自动增加,设置的小的话,又会遇到 RejectedExecutionHandler 问题。

附上简单的测试代码:

 static class TestCallable implements Callable<String> {
    private static Random random = new Random(System.currentTimeMillis());
    private int id;
    private String strType;

    TestCallable(String strType, int id) {
      this.strType = strType;
      this.id = id;
    }

    public String call() throws Exception {
      String strThreadName = String.format("%s[%d] in \"%s\"", strType, id, Thread.currentThread().getName());
      int sleepTime = 1000 + random.nextInt(1000);
      log.info("TestCallable, strType={}, will sleep {} ms", strThreadName, sleepTime);
      Thread.sleep(sleepTime);
      return strThreadName;
    }
  }

 @Test
  public void testExecutor() throws Exception {
    int cpuNums = Runtime.getRuntime().availableProcessors();   //获取当前系统的CPU 数目
    final int TASK_COUNT = cpuNums * 2;
    log.info("availableProcessors = {}", cpuNums);
    //newCachedThreadPool, newFixedThreadPool
    ThreadPoolExecutor executor = new ThreadPoolExecutor(0, cpuNums,
        0L, TimeUnit.MILLISECONDS,
        //通过设置 capacity 的值,从日志可以发现Java线程池的问题 -- 队列不满时,即使压了再多的任务,也不会创建新的线程
        new LinkedBlockingQueue<Runnable>(Integer.MAX_VALUE)); //cpuNums * 2

    assertEquals(0, executor.getCorePoolSize());
    assertEquals(cpuNums, executor.getMaximumPoolSize());
    assertEquals(0, getThreadNumberOfThreadPoolExecutor(executor));

    log.info("Before submit {} TestCallable", TASK_COUNT);
    //创建 TASK_COUNT 个任务并执行
    for (int i = 0; i < TASK_COUNT; i++) {
      Future<String> futureReturn = executor.submit(new TestCallable("Cached", i));
      resultList.add(futureReturn);
    }
    log.info("After submit all TestCallable");
    //assertEquals(1, getThreadNumberOfThreadPoolExecutor(executor)); //由于队列未满,只会创建 coreSize 个线程,不会继续增加

    for (Future<String> future : resultList) {
      log.info("Result: " + future.get());
      assertTrue(future.isDone());  //get会阻塞等待任务结束
    }
    log.info("After get all TestCallable result");

运行结果如下(从日志中可以发现, 即使队列中已经有很多任务在等待,但线程池中只有一个线程在运行):

[main] INFO com.fishjam.java.ThreadTest - availableProcessors = 8
[main] INFO com.fishjam.java.ThreadTest - Before submit 16 TestCallable
[main] INFO com.fishjam.java.ThreadTest - After submit all TestCallable
[pool-1-thread-1] INFO com.fishjam.java.ThreadTest - TestCallable, strType=Cached[0] in "pool-1-thread-1", will sleep 1186 ms
[main] INFO com.fishjam.java.ThreadTest - Result: Cached[0] in "pool-1-thread-1"
[pool-1-thread-1] INFO com.fishjam.java.ThreadTest - TestCallable, strType=Cached[1] in "pool-1-thread-1", will sleep 1763 ms
[main] INFO com.fishjam.java.ThreadTest - Result: Cached[1] in "pool-1-thread-1"
[pool-1-thread-1] INFO com.fishjam.java.ThreadTest - TestCallable, strType=Cached[2] in "pool-1-thread-1", will sleep 1326 ms
[main] INFO com.fishjam.java.ThreadTest - Result: Cached[2] in "pool-1-thread-1"
`
使用 ThreadPoolExecutor 创建线程池 使用 ThreadPoolExecutor 创建线程池 源码分析 ,ThreadPoolExecutor的构造函数 public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, ... 阅读详情

相关推荐

MuMu模拟器过检测实战:从硬件伪装到API欺骗的完整避坑指南

本文详细介绍了MuMu模拟器过检测的实战技术,从硬件伪装到API欺骗的全方位解决方案。通过修改CPU/GPU信息、内存分布、系统属性和行为模拟等关键技术,帮助用户有效绕过现代应用的模拟器检测机制,提升模拟器的隐蔽性和稳定性。

xxx12的博客 1404

ThreadPoolExecutor线程池异常被吞问题分析

一、起因: 在使用ScheduledThreadPoolExecutor执行一个定时任务时,发现执行一次后,任务就不再执行。 代码举例: private static final ScheduledExecutorService executorService = new ScheduledThreadPoolExecutor(1); private static final CountDownLatch countDownLatch = public static void main(String[

Soda_lw的博客 2163

Zabbix监控联想服务器XCC的SNMPv3配置实战

本文详细介绍了如何通过SNMPv3协议配置Zabbix监控联想服务器XCC的实战方法。文章从安全角度阐述了选择SNMPv3的必要性,并分步讲解了在XCC中启用SNMPv3、创建认证用户,以及在Zabbix中导入专用模板、创建主机并关联模板的完整流程,帮助运维人员实现对服务器硬件健康状态的自动化、安全监控。

weixin_29210727的博客 468

JAVA线程池和队列大小自动管理并动态调整的实现

1、复制一份CapacityLinkedBlockingQueue ,修改名字为ReWritedCapacityLinkedBlockingQueue ,目的是为了调整线程池队列大小。因为 CapacityLinkedBlockingQueue 中的capacity是被final定义了的,所以要想在运行时调整队列大小,需要重新定义。在 ReWritedCapacityLinkedBlockingQueue 中,将 capacity 修改为: private volatile int capacity; pu

weixin_42497784的博客 1875

【紫光同创PG2L200H开发板】盘古200Pro+开发板(MES2L676-200HP)

开发板 SMA接口符合标准 SMA 接口规范,可使用”内螺旋+插针“的 SMA 线连接板卡”外螺旋+插孔”的 SMA 接口进行通信,板卡 SMA 接口与 FPGA 的 HSST 收发器的一路 RX/TX 相连,TX信号和 RX 信号都是以差分信号方式通过隔直电容连接 FPGA 和 SMA 接口, TX 发送和 RX 接收数据速率高达 6.6Gb/s。为了减轻带电插拔造成对 FPGA 芯片的损坏,在设计上在 JTAG 信号位置添加了保护二极管来保证信号的电压在 FPGA 接受的范围,避免 FPGA 的损坏。

MYMINIEYE的博客 2887

C#中使用OpenCV的常用函数

c# opencv 常见操作

大黄鸭在发光的专栏 1080

Java-线程池动态修改大小

参数说明 corePoolSize:核心线程数大小,不管它们创建以后是不是空闲的。线程池需要保持 corePoolSize 数量的线程,除非设置了 allowCoreThreadTimeOut; maximumPoolSize:最大线程数,线程池中最多允许创建 maximumPoolSize 个线程; keepAliveTime:存活时间,如果经过 keepAliveTime 时间后,超过核心线程...

茶半香初 1万+

“华为杯”研究生数学建模竞赛2016年-【华为杯】A题:多无人机协同任务规划

题分别求解,保证了攻击方无人机滞留在防御方雷达有效探测范围内的时间总和最小,接着,通过提出巡检待命无人机的设想,型无人机携带炸弹的具体清单和攻击的目标清单),保证攻击方的无人机滞留防御方雷。在使用基于贪心算法的覆盖法时,覆盖的目标点中必须首先不含配备雷达站的目标点。步优化保证攻击方的无人机滞留防御方雷达有效探测范围内的时间总和最小,需首先。的“灵巧”炸弹,采用抛投方式对地攻击,即投放后炸弹以飞机投弹时的速度作抛物。运动,当炸弹接近目标后,可主动寻的攻击待打击的目标,因此炸弹落点位于目标中。

getusushu的博客 1037

【技术应用】java实现动态线程池ThreadPoolExecutor

java实现动态线程池ThreadPoolExecutor,代码示例,开源的动态可监控线程池框架(DynamicTp)推荐

dylan的博客 1902

AI预测彩票,使用chatgpt和lstm神经网络(文末附源码)

AI预测彩票,使用chatgpt和lstm神经网络(文末有彩蛋)

淘淘小窝 1万+

国科大作业考试资料-人工智能原理与算法-2024新编-第十一次作业整理

1、有一位教授想知道学生是否睡眠充足。每天,教授观察学生在课堂 上是否睡觉,并观察他们是否有红眼。教授获得如下的领域知识: (1)没有观察数据时,学生睡眠充足的先验概率为0.7。 (2)给定学生前一天睡眠充足为条件,学生在晚上睡眠充足的概率是0.8;如果前一天睡眠不充足,则是0.3。 (3)如果学生睡眠充足,则红眼的概率是0.2,否则是0.7。 (4)如果学生睡眠充足,则在课堂上睡觉的概率是0.1,否则是0.3。 将这些信息形式化为一个动态贝叶斯网络,使教授可以使用这个网络从观察序列中进行滤波和预

MatsumotoChrikk 1056

如何设置Java线程池ThreadPoolExecutor的每个参数

有时默认的拒绝策略可能不符合我们的需求,这时可以实现自己的。@Override// 自定义逻辑// 例如,可以记录日志或发送通知});提供了极大的灵活性来满足不同场景下的需求。通过合理配置workQueue等参数,可以有效地管理线程池的生命周期和性能。在实际应用中,通常需要结合具体业务场景进行性能测试和调优,以找到最适合的配置。

m0_50742275的博客 2439

huggingface下载提示huggingface_hub.errors.EntryNotFoundError:404 Client Error: (Request 1D: Root...如何解决?

🏆 本文收录于《全栈Bug调优(实战版)》专栏,致力于分享我在项目实战过程中遇到的各类Bug及其原因,并提供切实有效的解决方案。无论你是初学者还是经验丰富的开发者,本文将为你指引出一条更高效的Bug修复之路,助你早日登顶,迈向财富自由的梦想🚀!同时,欢迎大家关注、收藏、订阅本专栏,更多精彩内容正在持续更新中。让我们一起进步,Up!Up!Up!    备注: 部分问题/难题源自互联网,经过精心筛选和整理,结合数位十多年大厂实战经验资深大佬经验总结所得,数条可行方案供所需之人参考。

**My Coding Family** 1233

java线程池使用详解ThreadPoolExecutor使用示例

一 使用线程池的好处 二 Executor 框架 2.1 简介 2.2 Executor 框架结构(主要由三大部分组成) 1) 任务(Runnable /Callable) 2) 任务的执行(Executor) 3) 异步计算的结果(Future) 2.3 Executor 框架的使用示意图 三 (重要)ThreadPoolExecutor 类简单介绍 3.1 ThreadPoolExecutor 类分析 3.2 推荐使用 ThreadPoolExecutor 构造函数创建线程池 四 ..

xu_yong_lin的博客 5万+

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

大中型超市收银系统(可直接运行)

光步前台收银系统系统功能:商品销售、商品退货、挂单、收银员权限、会员销售、单品取消、整单取消、商品查询、脱机销售、脱机数据上传,基本资料下载,开钱箱、小票打印、收款结算,支持多币种付款方式(现金、储值卡、礼券、微信等),支持多种促销。运行环境:.net 4.0登陆信息用户名:1001 密码:123456内置商品信息,商品编码可输入00001000 - 00010000,测试效果相关功能键F5 结算 F9挂单 F11商品查询 F8退货 Insert单品取消 Del整单取消 F12开钱箱F2 会员 Ctrl+Z退出系统 Home 锁屏 相关源码待公开

Java 线程池 ThreadPoolExecutor 源码分析

线程池能够对线程进行有效的管理, 复用和数量上限的限制, 所以比起原始的 new Thread().start() 这种创建并启动线程的方式, 线程池的效率和性能都更好. Java 中的线程池是用 ThreadPoolExecutor 类来表示的. 我们今天就结合该类的源码来分析一下这个类内部对于线程的创建, 管理以及后台任务的调度等方面的执行原理. 我这里分析的是 JDK 1.8 的源码.

clevergump的专栏 1万+

数学建模模型总结

这是本人在两年内准备参加数学建模竞赛搜集到的模型资料,已经经过了本人的筛选和整理,希望能够对准备参加数学建模竞赛的学弟学妹们提供一些帮助!

Java ThreadPoolExecutor的拒绝策略

一、概述 在分析ThreadPoolExecutor的构造参数时,有一个RejectedExecutionHandler参数。 RejectedExecutionHandler是一个接口: public interface RejectedExecutionHandler { void rejectedExecution(Runnable r, ThreadPoolExecu...

悟鸣的技术博客 6686

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

【深度长文】深入分析Java线程池——ThreadPoolExecutor

一篇深入的线程池源码研究博客,图片形象生动、代码注释详细。

wzz2333的博客 1236

java线程池ThreadPoolExecutor原理源码分析

java线程池实现原理,线程池远吗分析

qq_34735262的博客 1849

Java 线程池ThreadPoolExecutor源码解读

线程池与其说他是复用Thread,不如说他是不断地向Thread中填充新的Runnable,然后调用run,减少了创建Thread的开销。这个是老生常谈的实现方法了,继承Thread的时候需要实现run,如果直接调用run的话是无法开启线程的。如果阻塞队列都放慢了,就会看非核心线程是否到了最大的线程数,如果达到了最大线程,就会执行拒绝策略。总的来说addWorker除了进行Worker的构建和添加到Workers之外,还进行了Worker中线程的启动,这块是真正执行我们定义的逻辑的地方。

allen_xu_2012_new的博客 974

关于Java线程池ThreadPoolExecutor相关介绍

线程池主要解决两个问题:一是当执行大量异步任务时线程池能够提供较好的性能。在不使用线程池时,每当需要执行异步任务时直接 new 一个线程来运行,而线程的创建和销毁是需要开销的。线程池里面的线程是可以服用的,不需要每次执行异步任务时都重新创建和销毁线程等。每个 ThreadPoolExecutor 也保留了一些基本的统计数据,比如当前线程池完成的任务数目等。

weixin_46448719的博客 1519

ThreadPoolExecutor线程池

是 Java 中功能最强大的线程池实现,允许你根据实际需求自定义线程池的行为。通过调整核心线程数、最大线程数、任务队列类型、拒绝策略等参数,可以灵活应对不同的并发任务需求。要注意合理设置线程池的参数,避免资源浪费或线程饥饿等问题,同时合理使用拒绝策略来处理线程池无法处理的任务。类中的submit方法是一个常用的 API,用于将一个Callable任务提交到线程池进行异步执行。你提供的代码片段展示了如何通过方法提交一个任务,并返回一个Future<T>对象,来表示任务的执行结果。

wangkun9581的博客 1151

Java 并发之线程池 ThreadPoolExecutor

顶层的接口,用来执行提交的 Runnable 任务。这个接口提供了一种将任务提交和任务运行机制(包括线程的使用、调度等)解耦的方式。总而言之,它是一个顶层接口。

xlh1191860939的博客 833

线程池ThreadPoolExecutor源码分析(上)

线程池是一种基于资源复用思想的池化技术。由线程池统一地去创建,回收线程,避免频繁地手动创建,销毁线程,以减少开销。阿里开发手册强制规范10,200,30,i < 10;i++) {});注意:本篇中提到的线程池,是JUC包下的线程池,非Tomcat的实现,Tomcat的线程池做过二次开发,和JUC的实现细节有所区别。

西岭千秋雪的博客 1114

java线程池ThreadPoolExecutor八种拒绝策略浅析

前言 谈到java的线程池最熟悉的莫过于ExecutorService接口了,jdk1.5新增的java.util.concurrent包下的这个api,大大的简化了多线程代码的开发。而不论你用FixedThreadPool还是CachedThreadPool其背后实现都是ThreadPo...

chihujiang3132的博客 1823

Java线程池:ThreadPoolExecutor原理解析

本文介绍了线程池的基本概念、主要参数、工作流程,以及 execute() 方法的源码分析,此外,还讨论了在实际应用中可能遇到的陷阱和问题。

u014800975的博客 1232

线程池 ThreadPoolExecutor 分析与实战

多线程并发执行可以提高程序的性能。特别是在多核处理器的环境下,多线程程序能发挥多核处理器的优势性能。

陈皮的JavaLib 2306
上一篇: 最简单的调试学习Hadoop Examples的方法
下一篇: 开源:通用的日志分析工具(LogViewer)
fishjam
博客等级 码龄23年 170粉丝 37原创
评论 1
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值