1.2.3 异步事件的简化处理

服务器应用程序在接受来自多个远程客户端的套接字连接请求时,如果为每个连接都分配其各自的线程并且使用同步I/O,那么就会降低这类程序的开发难度。

如果某个应用程序对套接字执行读操作而此时还没有数据到来,那么这个读操作将一直阻塞,直到有数据到达。在单线程应用程序中,这不仅意味着在处理请求的过程中将停顿,而且还意味着在这个线程被阻塞期间,对所有请求的处理都将停顿。为了避免这个问题,单线程服务器应用程序必须使用非阻塞I/O,这种I/O的复杂性要远远高于同步I/O,并且很容易出错。然而,如果每个请求都拥有自己的处理线程,那么在处理某个请求时发生的阻塞将不会影响其他请求的处理。

早期的操作系统通常会将进程中可创建的线程数量限制在一个较低的阈值内,大约在数百个(甚至更少)左右。因此,操作系统提供了一些高效的方法来实现多路I/O,例如Unix的select和poll等系统调用,要调用这些方法,Java类库需要获得一组实现非阻塞I/O的包(java.nio)。然而,在现代操作系统中,线程数量已得到极大的提升,这使得在某些平台上,即使有更多的客户端,为每个客户端分配一个线程也是可行的[1]

[1]NPTL线程软件包是专门设计用于支持数十万个线程的,在大多数Linux发布版本中都包含了这个软件包。非阻塞I/O有其自身的优势,但如果操作系统能更好地支持线程,那么需要使用非阻塞I/O的情况将变得更少。

Get Java并发编程实战 now with the O’Reilly learning platform.

O’Reilly members experience books, live events, courses curated by job role, and more from O’Reilly and nearly 200 top publishers.