当前位置: 首页 > news >正文

Java 线程池


线程池-终极奥义 —— 程序员的奴隶工厂

核心思想“宁可让线程累到猝死,也不让CPU闲着!”


1. 线程池七大参数(死亡轮盘)

ThreadPoolExecutor(  int corePoolSize,       // 正式工编制  int maximumPoolSize,    // 临时工最大数量(含正式工)  long keepAliveTime,     // 临时工摸鱼时间(超时开除)  TimeUnit unit,          // 时间单位(比如:分钟摸鱼)  BlockingQueue<Runnable> workQueue, // 任务候客区  ThreadFactory threadFactory,       // 奴隶生成器  RejectedExecutionHandler handler   // 拒绝策略(爆满时的骚操作)  
)  

暴力解读

  • 正式工(corePoolSize):就算没活干也得养着,池子的死忠粉
  • 临时工(maximumPoolSize - corePoolSize):忙时扩招,闲时砍头
  • 候客区(workQueue)
    • ArrayBlockingQueue:有界队列,像医院挂号窗口(排满就炸)
    • LinkedBlockingQueue:无界队列,像春运火车站(可能OOM)
    • SynchronousQueue:直通队列,像打麻将“一缺三”(没有等待区)

2. 线程池工作流程(修罗场)

(以银行柜台为喻,代码级暴力拆解)

public void execute(Runnable command) {  // 阶段1:正式工是否空闲?  if (workerCount < corePoolSize) {  if (addWorker(command, true))  // 创建正式工  return;  }  // 阶段2:扔到候客区排队  if (workQueue.offer(command)) {  // 突然发现池子关了?(二次检查骚操作)  if (isShutdown() && remove(command))  reject(command);  else if (workerCount == 0)  addWorker(null, false); // 保底一个临时工  }  // 阶段3:连候客区都满了?召唤临时工!  else if (!addWorker(command, false))  reject(command); // 彻底爆炸,执行拒绝策略  
}  

血腥流程

  1. 来新任务先找正式工(corePool)
  2. 正式工满?丢到候客区(workQueue)
  3. 候客区爆满?紧急招聘临时工(maxPool)
  4. 连临时工都招满?启动拒绝策略大屠杀

3. 拒绝策略(四大酷刑)

策略类行为现实比喻
AbortPolicy直接抛RejectedExecutionException“满了!滚!”(默认策略)
CallerRunsPolicy让提交任务的线程自己执行“你自己没长手吗?”
DiscardPolicy默默丢弃任务,装作无事发生渣男行为(不拒绝不负责)
DiscardOldestPolicy丢弃队列最老的任务,重试提交“老人就该死吗?”(社达主义)

代码级处决现场

// 自定义拒绝策略:记录日志+发告警  
new ThreadPoolExecutor.AbortPolicy() {  @Override  public void rejectedExecution(Runnable r, ThreadPoolExecutor e) {  log.error("他妈的任务炸了!", r);  sendAlert("服务器要死了!");  throw new RejectedExecutionException("老子不干了!");  }  
}  

4. 线程池底层(黑暗解剖)

Worker类 —— 奴隶の枷锁
private final class Worker extends AbstractQueuedSynchronizer implements Runnable {  final Thread thread; // 真正的苦力线程  Runnable firstTask;  // 处女任务(可能为null)  Worker(Runnable firstTask) {  this.firstTask = firstTask;  this.thread = getThreadFactory().newThread(this); // 工厂造人!  }  public void run() {  runWorker(this); // 开启无限受虐循环  }  
}  final void runWorker(Worker w) {  while (task != null || (task = getTask()) != null) { // 核心死亡循环!  try {  task.run(); // 执行任务(可能抛出异常)  } finally {  task = null;  }  }  
}  

黑暗秘密

  • 每个Worker包裹一个线程+一个初始任务
  • 用AQS实现不可重入锁(防止任务中重复获取锁)
  • getTask()方法从队列取任务时,会根据配置决定是否超时自杀
线程回收(断头台逻辑)
private Runnable getTask() {  for (;;) {  // 检查是否允许核心线程超时死亡  boolean timed = allowCoreThreadTimeOut || workerCount > corePoolSize;  try {  Runnable r = timed ?  workQueue.poll(keepAliveTime, TimeUnit.NANOSECONDS) :  workQueue.take(); // 阻塞直到有任务  if (r != null) return r;  } catch (InterruptedException retry) {}  // 超时后检查是否要自杀  if (workerCount > corePoolSize || allowCoreThreadTimeOut)  return null; // return null触发worker死亡  }  
}  

5. 四种预定义线程池(作死指南)

1. newFixedThreadPool —— 铁饭碗工厂

Executors.newFixedThreadPool(10);  
  • 队列:LinkedBlockingQueue(无界)
  • 风险:任务堆积直接OOM(OutOfMemoryError)
  • 使用场景:已知任务量可控的稳定负载

2. newCachedThreadPool —— 临时工敢死队

Executors.newCachedThreadPool();  
  • 队列:SynchronousQueue(直接传递)
  • 特点:线程数无上限,空闲60秒自杀
  • 风险:瞬间创建大量线程导致CPU爆炸
  • 使用场景:短命异步任务(比如HTTP请求)

3. newSingleThreadExecutor —— 寡头垄断

Executors.newSingleThreadExecutor();  
  • 本质:core=max=1的FixedThreadPool
  • 队列:无界队列
  • 使用场景:需要任务顺序执行(但依然有OOM风险)

4. newScheduledThreadPool —— 时间管理大师

Executors.newScheduledThreadPool(5);  
  • 特殊技能:定时任务(scheduleAtFixedRate)
  • 底层:DelayedWorkQueue(按时间排序的堆结构)
  • 坑爹点:异常会导致定时任务停止

线程池(作死圣经)

  1. 禁止用Executors创建线程池(容易OOM),推荐手动new ThreadPoolExecutor
  2. CPU密集型:核心线程数 ≈ CPU核数(避免过多上下文切换)
  3. IO密集型:核心线程数 ≈ CPU核数 * 2(比如数据库连接池)
  4. 队列选择原则
    • 要控制最大任务量 → ArrayBlockingQueue
    • 要无限堆积 → LinkedBlockingQueue(准备好棺材)
    • 要直接传递 → SynchronousQueue(配合maxPoolSize使用)
  5. 监控必备:继承ThreadPoolExecutor,重写beforeExecute/afterExecute

(掀桌子怒吼)现在!立刻!马上!给老子写个把CPU干到100%的线程池!

http://www.xdnf.cn/news/46945.html

相关文章:

  • 2024新版仿蓝奏云网盘源码,已修复已知BUG,样式风格美化,可正常运营生产
  • 【C++】 —— 笔试刷题day_22
  • 易语言验证京东滑块轨迹算法
  • 十倍开发效率 - IDEA插件之 Maven Helper
  • leetcode刷题日记——快乐数
  • 【信息安全工程师备考笔记】第一章 网络信息安全概述
  • 【C++】二叉搜索树
  • 线性回归之正则化(regularization)
  • C++入门基础:引用,auto自动关键字,内联函数,范围for循环
  • 【iOS】alloc init new底层原理
  • 代收代付到底是什么?
  • 【英语语法】词法---副词
  • AIGC赋能插画创作:技术解析与代码实战详解
  • 大模型应用案例:主动提问式的 AI 面试官(接入 DeepSeek)
  • 【特殊场景应对3】创意岗简历骚操作:作品集链接的正确打开方式
  • deepseek + kimi制作PPT
  • 01背包简介
  • LeetCode第159题_至多包含两个不同字符的最长子串
  • Kubernetes相关的名词解释-关于组件分类(8)
  • 插叙的作用
  • 【2025软考高级架构师】——计算机系统基础(7)
  • gma 2.1.4 (2025.04.18) | GmaGIS V0.0.1a3 更新日志
  • 【读书笔记·VLSI电路设计方法解密】问题64:什么是芯片的功耗分析
  • JavaWeb 1.HTML+CSS (黑马JavaWeb课程笔记)
  • 交换机端口安全
  • C++学习之游戏服务器开发⑩ZINX的TCP通道实现
  • 基于 Vue3 + ECharts + GeoJson 实现区域地图钻取功能详解
  • 大模型在胆管结石(无胆管炎或胆囊炎)预测及治疗方案制定中的应用研究
  • 【perf】perf工具的使用生成火焰图
  • 自由的控件开发平台:飞帆中使用 css 和 js 库