通道(Channel)是java.nio的第二个主要创新。它们既不是一个扩展也不是一项增强,而是全新、极好的Java I/O示例,提供与I/O服务的直接连接。Channel用于在字节缓冲区和位于通道另一侧的实体(通常是一个文件或套接字)之间有效地传输数据。

通道可以形象地比喻为银行出纳窗口使用的气动导管。您的薪水支票就是您要传送的信息,载体(Carrier)就好比一个缓冲区。您先填充缓冲区(将您的支票放到载体上),接着将缓冲“写”到通道中(将载体丢进导管中),然后信息负载就被传递到通道另一侧的I/O服务(银行出纳员)。该过程的回应是:出纳员填充缓冲区(将您的收据放到载体上),接着开始一个反方向的通道传输(将载体丢回到导管中)。载体就到了通道的您这一侧(一个填满了的缓冲区正等待您的查验),然后您就会flip缓冲区(打开盖子)并将它清空(移除您的收据)。现在您可以开车走了,下一个对象(银行客户)将使用同样的载体(Buffer)和导管(Channel)对象来重复上述过程。

您可以从顶层的Channel接口看到,对所有通道来说只有两种共同的操作:检查一个通道是否打开(IsOpen())和关闭一个打开的通道(close())。图3-2显示,所有有趣的东西都是那些实现Channel接口以及它的子接口的类。

通道是访问I/O服务的导管。I/O可以分为广义的两大类别:文件IO和网络IO . 那么相应地有两种类型的通道,它们是文件(file)通道和套接字(socket)通道。这两种类型的通道主要对应三个通道相关的类:一个FileChannel类和三个socket通道类:SocketChannel、ServerSocketChannel和DatagramChannel。通道可以以多种方式创建。Socket通道有可以直接创建新socket通道的工厂方法。但是一个FileChannel对象却只能通过在一个打开的RandomAccessFile、FileInputStream或FileOutputStream对象上调用getChannel( )方法来获取。您不能直接创建一个FileChannel对象。

几种通道的创建方式:

SocketChannel sc = SocketChannel.open( );
sc.connect (new InetSocketAddress ("somehost", someport));
ServerSocketChannel ssc = ServerSocketChannel.open( );
ssc.socket( ).bind (new InetSocketAddress (somelocalport));
DatagramChannel dc = DatagramChannel.open( );
RandomAccessFile raf = new RandomAccessFile ("somefile", "r");
FileChannel fc = raf.getChannel( );

通道会连接到一个特定IO服务,且通道实例的性能收到它连接的IO服务的特性的限制,比如说,一个连接到只读文件的Cchannel实例不能进行写操作,即使该实例所属的类有write()方法,所有,程序员在操作通道的时候,要知道通道是如何打开的,避免尝试一个底层IO服务不允许的操作

通道可以以阻塞的方式或者非阻塞的方式来运行,非阻塞的通道永远不会让调用的线程休眠,请求的操作要么立即完成,要么返回一个结果,表明未进行任何操作,只有面向流的通道(stream-oriented),如sockets和pipes才能以非阻塞的模式来运行,面向文件的通道都是以阻塞的方式来运行的.

通道不能被重复利用:

与缓冲区不同,通道不能被重复利用,一个打开的通道就代表一个与特定IO服务的特定连接,并封装该连接的状态.当通道关闭的时候,这个特定的连接会丢失,然后,通道将不再连接任何东西

posted on 2018-07-19 22:52  梦中彩虹  阅读(707)  评论(0编辑  收藏  举报