通道(Channel)用于在字节缓冲区(通道只能在字节缓冲区上操做)和位于通道另外一侧的实体(一般是一个文件或套接字)之间有效地传输数据,而且通道每每是和操做系统的文件描述符(File Descriptor)和文件句柄(File Handle)对应的,能够用最小的总开销来访问操做系统自己的I/O服务html
类图结构以下所示java
基本的Channel接口源码ios
package java.nio.channels; public interface Channel { public boolean isOpen( ); //通道是否打开 public void close( ) throws IOException; //关闭一个打开的通道 }
InterruptibleChannel是一个标记接口,标示该通道是能够中断的(Interruptible),若是链接可中断通道的线程被中断,那么该通道会以特别的方式工做。大多数但非所有的通道都是能够中断的dom
类层次结构中有两个类位于一个不一样的包:java.nio.channels.spi。这两个类AbstractInterruptibleChannel和AbstractSelectableChannel,它们分别为可中断的(interruptible)和可选择的(selectable)的通道实现提供所需的经常使用方法socket
IO能够分为File I/O和Stream I/O,通道也能够分为文件(file)通道和套接字(socket)通道,最经常使用的分别是FileChannel类和三个socket通道类:SocketChannel、ServerSocketChannel和DatagramChannelspa
Socket通道有能够直接建立新socket通道的工厂方法。可是一个FileChannel对象却只能经过在一个打开的RandomAccessFile、FileInputStream或FileOutputStream对象上调用getChannel( )方法来获取操作系统
package com.henrysun.javaSE.niostudy; import java.io.IOException; import java.io.RandomAccessFile; import java.net.InetSocketAddress; import java.nio.channels.DatagramChannel; import java.nio.channels.FileChannel; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; /** * 打开通道 */ public class ChannelOpen { /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { SocketChannel sc = SocketChannel.open(); sc.connect(new InetSocketAddress("somehost", 8080)); ServerSocketChannel ssc = ServerSocketChannel.open(); ssc.socket().bind(new InetSocketAddress(8090)); DatagramChannel dc = DatagramChannel.open(); RandomAccessFile raf = new RandomAccessFile("somefile", "r"); FileChannel fc = raf.getChannel(); } }
上面的类图结构,大部分零乱部分移除能够获得以下的UML图.net
public interface ReadableByteChannel extends Channel { public int read(ByteBuffer dst) throws IOException; } public interface WritableByteChannel extends Channel { public int write(ByteBuffer src) throws IOException; } public interface ByteChannel extends ReadableByteChannel, WritableByteChannel { }
通道能够是单向的或者双向的,一个channel类可能实现定义read( )方法的ReadableByteChannel接口,而另外一个channel类也许实现WritableByteChannel接口以提供write( )方法。实现这两种接口其中之一的类都只能在一个方向上传输数据。若是一个类同时实现这两个接口,那么它能够双向传输数据。这对于sockets不是问题,由于它一直是双向的,可是从FileInputStream对象的getChannel( )方法获取的FileChannel对象是只读的,由于FileInputStream对象老是以read-only的权限打开文件,尽管FileChannel实现了ByteChannel接口。调用write( )方法将抛出未经检查的NonWritableChannelException异常线程
通道能够以阻塞和非阻塞模式运行。非阻塞模式的通道永远不会让调用的线程休眠。请求的操做要么当即完成,要么返回一个结果代表未进行任何操做。只有面向流的(stream-oriented)的通道,如sockets和pipes才能使用非阻塞模式code
注:socket通道类从SelectableChannel引伸而来。从SelectableChannel引伸而来的类能够和支持有条件的选择(readiness selectio)的选择器(Selectors)一块儿使用。将非阻塞I/O和选择器组合起来可使您的程序利用多路复用I/O(multiplexed I/O)