当前位置: 首页 > 科技观察

并发编程领域的Thread-Per-Message设计模式到底是什么?

时间:2023-03-15 01:09:12 科技观察

并发编程的核心是什么?同步、互斥、分工、并发编程。有哪些设计模式可以解决分工问题?委托他人代办事情有个好处,就是可以专心做自己的事情。编程也是如此。比如写一个HTTPServer,很明显在主线程只能接收请求,不能处理HTTP请求,因为如果在主线程处理HTTP请求,同一时间只能处理一个请求,太慢了!这时候可以采用委托的思路,创建一个子线程,委托子线程处理HTTP请求。这种show操作就是并发领域的Thread-Per-Message模式(以下简称TPM):为每个任务分配一个独立的线程。这也是最简单的分工方案。Java线程实现TPMTPM最经典的应用场景就是网络编程的服务器实现。服务端为每个客户端请求创建一个独立的线程,当线程处理完请求后,自动销毁。这是并发处理网络请求的最简单方法。比如服务器端的echo程序,但是这个实现在实际生产中是不能用的,因为Java线程真的是一个重量级的对象:创建线程比较耗时,线程占用的内存比较大大的。因此,没有必要为每个请求创建一个新线程。适用于互联网的高并发场景。TPM只是一个幻想的国家吗?如果换成其他实现方式,你可能会想到线程池。方向很好,但是引入线程池也增加了复杂度。换个角度看问题,语言、工具、框架应该帮助我们实现更高性能的解决方案,而不是否定它们。TPM作为最简单的分工解决方案,Java语言是无法支持的。很明显,它是Java语言自己设计的。问题。在Java语言中,Java线程与操作系统线程是一一对应的。这种方式本质上是将Java线程的调度权委托给了操作系统,而操作系统在这方面已经非常成熟,所以这种方式的好处是稳定可靠,但也继承了操作系统线程的缺点:高创建成本。为了解决这个缺点,Java并发包提供了线程池等工具类。长期以来,这种想法一直是一种非常安全的解决方案,但这种解决方案并不是唯一的。业界还有另外一种解决方案:轻量级线程。这个方案在Java领域并不知名,但它本质上和Go中的coroutines一样是一个轻量级的线程。它的创建成本很低,类似于创建一个普通对象;而且创建速度和内存占用至少比os线程高一个数量级,所以基于轻量级线程实现TPM完全没有问题。Java也意识到轻量级线程的重要性。OpenJDK的Loom项目就是为了解决Java语言中轻量级线程的问题。Loom中的轻量级线程称为纤程。使用Fiber实现TPM。在设计轻量级线程时,Loom也充分参考了Java线程目前的用法,所以学习成本还是很低的。只需将newThread(()->{…}).start()替换为Fiber.schedule(()->{})。在Java的高并发领域,虽然不可行,但是对于一些并发较低的异步场景,比如定时任务,使用TPM是没有问题的。本文转载自微信公众号「JavaEdge」,可通过以下二维码关注。转载本文请联系JavaEdge公众号。