一、阻塞与非阻塞
- 传统的IO 流都是阻塞式的。也就是说,当一个线程调用read() 或write() 时,该线程被阻塞,直到有一些数据被读取或写入,该线程在此期间不能执行其他任务。因此,在完成网络通信进行IO 操作时,由于线程会阻塞,所以服务器端必须为每个客户端都提供一个独立的线程进行处理,当服务器端需要处理大量客户端时,性能急剧下降。
- Java NIO 是非阻塞模式的。当线程从某通道进行读写数据时,若没有数据可用时,该线程可以进行其他任务。线程通常将非阻塞IO 的空闲时间用于在其他通道上执行IO 操作,所以单独的线程可以管理多个输入和输出通道。因此,NIO 可以让服务器端使用一个或有限几个线程来同时处理连接到服务器端的所有客户端。
二、选择器(Selector)
- 选择器(Selector)是SelectableChannle 对象的多路复用器,Selector 可以同时监控多个SelectableChannel 的IO 状况,也就是说,利用Selector 可使一个单独的线程管理多个Channel。Selector 是非阻塞IO 的核心。
- SelectableChannle 的结构如下图:
- 选择器(Selector)的应用
当调用register(Selector sel, int ops) 将通道注册选择器时,选择器对通道的监听事件,需要通过第二个参数ops 指定。
可以监听的事件类型(可使用SelectionKey 的四个常量表示):
读: SelectionKey.OP_READ (1)
写: SelectionKey.OP_WRITE (4)
连接: SelectionKey.OP_CONNECT(8)
接收: SelectionKey.OP_ACCEPT (16)
若注册时不止监听一个事件,则可以使用“位或”操作符连接。
- SelectionKey
SelectionKey:表示SelectableChannel 和Selector 之间的注册关系。每次向选择器注册通道时就会选择一个事件(选择键)。选择键包含两个表示为整数值的操作集。操作集的每一位都表示该键的通道所支持的一类可选择操作。
- Selector 的常用方法
- SocketChannel
Java NIO中的SocketChannel是一个连接到TCP网络套接字的通道。
操作步骤:
打开SocketChannel
读写数据
关闭SocketChannel
Java NIO中的ServerSocketChannel 是一个可以监听新进来的TCP连接的通道,就像标准IO中的ServerSocket一样
- DatagramChannel
Java NIO中的DatagramChannel是一个能收发UDP包的通道。
操作步骤:
打开DatagramChannel
接收/发送数据
三、管道(Pipe)
Java NIO 管道是2个线程之间的单向数据连接。Pipe有一个source通道和一个sink通道。数据会被写到sink通道,从source通道读取。
四、NIO.2
随着JDK 7 的发布,Java对NIO进行了极大的扩展,增强了对文件处理和文件系统特性的支持,以至于我们称他们为NIO.2。因为NIO 提供的一些功能,NIO已经成为文件处理中越来越重要的部分。
五、Path 与Paths
java.nio.file.Path 接口代表一个平台无关的平台路径,描述了目录结构中文件的位置。
Paths 提供的get() 方法用来获取Path 对象:
Pathget(String first, String … more) : 用于将多个字符串串连成路径。
Path常用方法:
boolean endsWith(String path) : 判断是否以path 路径结束
boolean startsWith(String path) : 判断是否以path 路径开始
boolean isAbsolute() : 判断是否是绝对路径
Path getFileName() : 返回与调用Path 对象关联的文件名
Path getName(int idx) : 返回的指定索引位置idx 的路径名称
int getNameCount() : 返回Path 根目录后面元素的数量
Path getParent() :返回Path对象包含整个路径,不包含Path 对象指定的文件路径
Path getRoot() :返回调用Path 对象的根路径
Path resolve(Path p) :将相对路径解析为绝对路径
Path toAbsolutePath() : 作为绝对路径返回调用Path 对象
String toString() :返回调用Path 对象的字符串表示形式
六、Files 类
java.nio.file.Files 用于操作文件或目录的工具类。
Files常用方法:
Path copy(Path src, Path dest, CopyOption … how) : 文件的复制
PathcreateDirectory(Path path, FileAttribute<?> … attr) : 创建一个目录
Path createFile(Path path, FileAttribute<?> … arr) : 创建一个文件
void delete(Path path) : 删除一个文件
Path move(Path src, Path dest, CopyOption…how) : 将src 移动到dest 位置
long size(Path path) : 返回path 指定文件的大小
Files常用方法:用于判断
boolean exists(Path path, LinkOption … opts) : 判断文件是否存在
boolean isDirectory(Path path, LinkOption … opts) : 判断是否是目录
boolean isExecutable(Path path) : 判断是否是可执行文件
boolean isHidden(Path path) : 判断是否是隐藏文件
boolean isReadable(Path path) : 判断文件是否可读
boolean isWritable(Path path) : 判断文件是否可写
boolean notExists(Path path, LinkOption … opts) : 判断文件是否不存在
public static <A extends BasicFileAttributes> A readAttributes(Path path,Class<A> type,LinkOption... options) : 获取与path 指定的文件相关联的属性。
Files常用方法:用于操作内容
SeekableByteChannel newByteChannel(Path path, OpenOption…how) : 获取与指定文件的连接,how 指定打开方式。
DirectoryStream newDirectoryStream(Path path) : 打开path 指定的目录
InputStream newInputStream(Path path, OpenOption…how):获取InputStream 对象
OutputStream newOutputStream(Path path, OpenOption…how) : 获取OutputStream 对象