由于传统的Socket类和ServerSocket类中提供的与建立连接和数据传输相关的方法都是阻塞式的,套接字通道提供了非阻塞式的和多路复用的套接字连接。多路复用套接字需要通过一个选择器(Selector)来对所有的套接字通道进行管理监听,当其中的某些套接字通道上有Selector感兴趣的事件发生的时候,这个通道就会变成可用的状态,然后可以进行各种通道操作。不过需要在一开始的时候把我们需要监听的套接字通道注册到选择器(Selector)上,以表明我们需要由选择器来监听这个套接字通道。
网上有一比较好的隐喻可以说明套接字的阻塞和非阻塞方法,摘抄如下:
一辆从 A 开往 B 的公共汽车上,路上有很多点可能会有人下车。司机不知道哪些点会有哪些人会下车,对于需要下车的人,如何处理更好?
2. 每个人(相当于套接字通道)告诉售票员(相当于Selector)自己的目的地(相当于套接字的事件),然后睡觉,司机(相当于CPU)只和售票员交互,到了某个点由售票员通知乘客下车。 ( 类似非阻塞 ),很显然,每个人要到达某个目的地可以认为是一个线程,司机可以认为是 CPU 。在阻塞式里面,每个线程需要不断的轮询,上下文切换,以达到找到目的地的结果。而在非阻塞方式里,每个乘客 ( 线程 ) 都在睡觉 ( 休眠 ) ,只在真正外部环境准备好了才唤醒,这样的唤醒肯定不会阻塞。