惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

AWS News Blog
AWS News Blog
N
Netflix TechBlog - Medium
Hugging Face - Blog
Hugging Face - Blog
OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - Franky
Apple Machine Learning Research
Apple Machine Learning Research
H
Help Net Security
博客园 - 聂微东
Security Archives - TechRepublic
Security Archives - TechRepublic
酷 壳 – CoolShell
酷 壳 – CoolShell
Cisco Talos Blog
Cisco Talos Blog
人人都是产品经理
人人都是产品经理
I
Intezer
C
CERT Recently Published Vulnerability Notes
博客园 - 三生石上(FineUI控件)
Simon Willison's Weblog
Simon Willison's Weblog
Project Zero
Project Zero
The Register - Security
The Register - Security
F
Full Disclosure
Scott Helme
Scott Helme
Cyberwarzone
Cyberwarzone
U
Unit 42
P
Proofpoint News Feed
Engineering at Meta
Engineering at Meta
钛媒体:引领未来商业与生活新知
钛媒体:引领未来商业与生活新知
NISL@THU
NISL@THU
T
Tor Project blog
A
Arctic Wolf
Y
Y Combinator Blog
I
InfoQ
M
MIT News - Artificial intelligence
P
Privacy & Cybersecurity Law Blog
Know Your Adversary
Know Your Adversary
Google DeepMind News
Google DeepMind News
Vercel News
Vercel News
V
Vulnerabilities – Threatpost
C
Cybersecurity and Infrastructure Security Agency CISA
Latest news
Latest news
量子位
N
News and Events Feed by Topic
T
The Blog of Author Tim Ferriss
H
Hackread – Cybersecurity News, Data Breaches, AI and More
Hacker News - Newest:
Hacker News - Newest: "LLM"
博客园_首页
S
Securelist
L
LINUX DO - 最新话题
T
Troy Hunt's Blog
The Cloudflare Blog
The GitHub Blog
The GitHub Blog
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org

咸糖 - 自律者自由

2025 年终总结:降噪、重构与长期主义 在新加坡和新山吃过最好的食物(持续更新) 写给还在迷茫的你:我的三本大学回忆 2024 年终总结 Neovim: No Crash Incremental Selection 2022 年终总结 使用 neovim 作为 PDE(个性化开发环境) shell 是一个不错的生产力工具 使用二八法则省力地学习 awk 肉身翻墙新加坡安顿指南 使用 Docker Compose 建立你自己的开发环境 关于编写可维护的代码的一些实践与想法 我为什么使用双向链接做笔记? 关于焦虑和拖延症 Golang: 如何处理日渐膨胀的 interface 使用番茄工作法来更好的利用你的时间 Unix 如何杀死一个进程和它的子孙进程? Golang: 让你的零值更有用 使用 Mock 和 Interface 进行 Golang 单测 关于 Golang Slice 的一些细节 总结一些计算机常用的原则 重新学习英语语法 上班族近期小半年入门投资基金组合的学习与实践经历 疫情期间的肉身翻墙新加坡指南 About me 软技能:大厂底层员工打工指南 软技能:我是如何获取知识与信息的? 分布式的令牌桶算法的实现 实现一个AtomicInteger GC root 在哪里? 什么是 Minor GC/Major GC 漏桶算法的设计与实现 剑指offer 单例模式 TCP 针对面试学习 Akka 源码解析 How to learn scala AES 需要限制 SEED 长度 Java 如何区分==与.equals()方法 2018年年度总结 Java 集合扩容
Actor 如何处理阻塞消息
xiantang · 2020-01-15 · via 咸糖 - 自律者自由

文章目录

【注意】最后更新于 December 29, 2025,文中内容可能已过时,请谨慎使用。

观察了一下业务的代码中发现在 Actor 中采用了很多

import scala.concurrent.ExecutionContext.Implicits.global

来作为 Actor 内部的执行 Future 的线程池,之前觉得好像也没啥问题。 但是在看完 akka 源码后发现好像有些不妥。

简单的讲一下 Actor 的架构吧

当一个Actor 向另外一个 Actor 中发送信息会将这条信息发送到接受的Actor的 mailbox 中

mailbox 是一个实现 Runnable 的类,所以可以用线程池执行,所以每当你向一个Actor 发送一条消息的时候 其实是用 接受者的 Dispatcher 来执行这条消息的。

但是问题是如果你的应用是 IO 密集型的应用

那么无论你使用 Actor 的默认的 defaultDispather 或者 Future 的global 隐式转换方式,都会因为线程池的核心线程被阻塞任务限制,导致线程饥饿

并且因为ForkJoinPool 的实现,是一个适合计算的线程池。

所以这里给出两个方案

  1. 对于 IO 密集型的任务可以采用自定义线程池的方式进行解决

    但是如果突发的请求很多,仍然会导致线程池中线程都在阻塞,无法立马响应请求的情况。

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
implicit val blockingDispatcher: MessageDispatcher = context.system.dispatchers.lookup("blocking-io-dispatcher")

blocking-io-dispatcher {
  type = Dispatcher
  executor = "thread-pool-executor"
  thread-pool-executor {
   fixed-pool-size = 32
  }
  throughput = 1
}
  1. 使用 scala.concurrent.blocking对于阻塞时间较长的任务,可以使用这个函数来包裹你的任务
1
2
3
4
5
6
7
Future {
  println("starting Future: " + n)
  blocking {
    Thread.sleep(3000)
  }
  println("ending Future: " + n)
}

在执行的时候会在 ForkJoinPool 会使用当前的线程作为拓展池中的线程,也就是超出最大线程数,再额外开出一个线程进行计算。 是 ForkJoinPool 在面对阻塞的情况下使用的方案。 blocking 函数其实在实现了 ForkJoinPool.ManagedBlocker 会给分配 Fork/Join Pool 给一个线程,执行阻塞的操作。与 ForkJoinPool 的传统方式不同,所以不会产生线程饥饿的现象。

文章作者 xiantang

上次更新 2025-12-29 (4c152d04)

赞赏支持

微信打赏 支付宝打赏