Java NIO学习8(Selector 补充版1)

来源:互联网 发布:数据采集器工作原理 编辑:程序博客网 时间:2024/06/05 11:59

很大一部分来自于java nio那不能书上的内容!

Java nio的电子版 网上有的是,给个地址:java nio 中文版


新的socket通道类可以运行非阻塞模式并且是可选择的。这两个性能可以激活大程序(如网络服务器和中间件组件)巨大的可伸缩性和灵活性。本节中我们会看到,再也没有为每个socket连接

使用一个线程的必要了,也避免了管理大量线程所需的上下文交换总开销。借助新的NIO类,一个或几个线程就可以管理成百上千的活动socket连接了并且只有很少甚至可能没有性能损失。


请注意DatagramChannel和SocketChannel实现定义读和写功能的接口而ServerSocketChannel不实现。ServerSocketChannel负责监听传入的连接和创建新的SocketChannel对象,它本身从不传输数据。在我们具体讨论每一种socket通道前,您应该了解socket和socket通道之间的关系。之前的章节中有写道,通道是一个连接I/O服务导管并提供与该服务交互的方法。就某个socket而言,它不会再次实现与之对应的socket通道类中的socket协议API,而java.net中已经存在的socket通道都可以被大多数协议操作重复使用。全部socket通道类(DatagramChannel、SocketChannel和ServerSocketChannel)在被实例化时都会创建一个对等socket对象。这些是我们所熟悉的来自java.net的类(Socket、ServerSocket和DatagramSocket),它们已经被更新以识别通道。对等socket可以通过调用socket( )方法从一个通道上获取。此外,这三个java.net类现在都有getChannel( )方法。


非阻塞模式
Socket通道可以在非阻塞模式下运行。这个陈述虽然简单却有着深远的含义。传统Java socket的阻塞性质曾经是Java程序可伸缩性的最重要制约之一。非阻塞I/O是许多复杂的、高性能的程序构建的基础。要把一个socket通道置于非阻塞模式,我们要依靠所有socket通道类的公有超级类:SelectableChannel。下面的方法就是关于通道的阻塞模式的:

 public abstract class SelectableChannel extends AbstractChannel implements Channel { // This is a partial API listing
 public abstract void configureBlocking (boolean block) throws IOException; 
public abstract boolean isBlocking( );
public abstract Object blockingLock( ); } }


有条件的选择(readiness selection)是一种可以用来查询通道的机制,该查询可以判断通道是否准备好执行一个目标操作,如读或写。非阻塞I/O和可选择性是紧密相连的,那也正是管理阻塞模式的API代码要在SelectableChannel超级类中定义的原因。SelectableChannel的剩余API将在第四章中讨论。设置或重新设置一个通道的阻塞模式是很简单的,只要调用configureBlocking( )方法即可,传递参数值为true则设为阻塞模式,参数值为false值设为非阻塞模式。真的,就这么简单!您可以通过调用isBlocking( )方法来判断某个socket通道当前处于哪种模式:

 SocketChannel sc = SocketChannel.open( ); sc.configureBlocking (false);  // nonblocking ...  if ( ! sc.isBlocking( )) {  doSomething (cs);  }

服务器端的使用经常会考虑到非阻塞socket通道,因为它们使同时管理很多socket通道变得更容易。但是,在客户端使用一个或几个非阻塞模式的socket通道也是有益处的,例如,借助非阻塞socket通道,GUI程序可以专注于用户请求并且同时维护与一个或多个服务器的会话。在很多程序上,非阻塞模式都是有用的。偶尔地,我们也会需要防止socket通道的阻塞模式被更改。API中有一个blockingLock( )方法,该方法会返回一个非透明的对象引用。返回的对象是通道实现修改阻塞模式时内部使用的。只有拥有此对象的锁的线程才能更改通道的阻塞模式(对象的锁是用同步的Java密码获取的,它不同于我们在3.3节中介绍的lock( )方法)。对于确保在执行代码的关键部分时socket通道的阻塞模式不会改变以及在不影响其他线程的前提下暂时改变阻塞模式来说,这个方法都是非常方便的。

Socket socket = null;Object lockObj = serverChannel.blockingLock( );// have a handle to the lock object, but haven't locked it yet // may block here until lock is acquiredsynchronize (lockObj) { // This thread now owns the lock; mode can't be changed boolean prevState = serverChannel.isBlocking( );}serverChannel.configureBlocking (false); socket = serverChannel.accept( );serverChannel.configureBlocking (prevState); }// lock is now released, mode is allowed to change if (socket != null) {doSomethingWithTheSocket (socket);}




原创粉丝点击