知识准备

简单地说,线程模型指定了操作系统、编程语言、框架或者应用程序的上下文中的线程管理的关键方面。

显而易见地,如何以及何时创建线程将对应用程序代码的执行产生显著的影响,因此开发人员需要理解与不同模型相关的权衡。

无论是他们自己选择模型,还是通过采用某种编程语言或者框架隐式地获得它,这都是真实的。

在本章中,我们将详细地探讨Netty 的线程模型。

它强大但又易用,并且和Netty 的一贯宗旨一样,旨在简化你的应用程序代码,同时最大限度地提高性能和可维护性。

我们还将讨论致使选择当前线程模型的经验。

如果你对Java 的并发API(java.util.concurrent)有比较好的理解,那么你应该会发现在本章中的讨论都是直截了当的。

如果这些概念对你来说还比较陌生,或者你需要更新自己的相关知识,那么由Brian Goetz 等编写的《Java 并发编程实战》 (Addison-Wesley Professional, 2006)这本书将是极好的资源。

相关阅读

java thread Executor 框架

线程模型

在这一节中,我们将介绍常见的线程模型,随后将继续讨论Netty 过去以及当前的线程模型,并评审它们各自的优点以及局限性。

正如我们在本章开头所指出的,线程模型确定了代码的执行方式。由于我们总是必须规避并发执行可能会带来的副作用,所以理解所采用的并发模型(也有单线程的线程模型)的影响很重要。

忽略这些问题,仅寄希望于最好的情况(不会引发并发问题)无疑是赌博——赔率必然会击败你。

因为具有多核心或多个CPU 的计算机现在已经司空见惯,大多数的现代应用程序都利用了复杂的多线程处理技术以有效地利用系统资源。

相比之下,在早期的Java 语言中,我们使用多线程处理的主要方式无非是按需创建和启动新的Thread 来执行并发的任务单元——一种在高负载下工作得很差的原始方式。

Java 5 随后引入了Executor API,其线程池通过缓存和重用Thread 极大地提高了性能。

池化

基本的线程池化模式可以描述为:

  1. 从池的空闲线程列表中选择一个 Thread,并且指派它去运行一个已提交的任务(一个 Runnable 的实现);

  2. 当任务完成时,将该 Thread 返回给该列表,使其可被重用。

ps: 池化是一种面对昂贵的资源,非常好的思维。

虽然池化和重用线程相对于简单地为每个任务都创建和销毁线程是一种进步,但是它并不能消除由上下文切换所带来的开销,其将随着线程数量的增加很快变得明显,并且在高负载下愈演愈烈。

此外,仅仅由于应用程序的整体复杂性或者并发需求,在项目的生命周期内也可能会出现其他和线程相关的问题。

简而言之,多线程处理是很复杂的。在接下来的章节中,我们将会看到Netty 是如何帮助简化它的。

个人收获

  1. 池化拥有了多线程的优越性和避免创建的资源代价,但是多线程的上下问切换无法避免。

  2. 多线程同时也带来了并发的复杂性,感觉 netty 在这两点的设计上都非常的优异。

参考资料

《Netty in Action》 P113