原文地址: link.
最近看到一个听不错的Java NIO的学习资料,不过是英文的,翻译谷歌翻译有时又不是很通顺,所以自己照着谷歌的翻译自己理了一遍!
1.Java NIO教程
Java NIO(新IO)是Java的替代IO API(来自Java 1.4),意味着替代标准 Java IO和Java Networking API。Java NIO提供了与标准IO API不同的使用IO的方式。
Java NIO:Channels(通道)and Buffers(缓冲区)
在标准IO API中,你使用字节流和字符流。在NIO中,你使用通道和缓冲区。数据总是从通道读入缓冲区,或从缓冲区写入通道。
Java NIO:Non-blocking IO(非阻塞IO)
Java NIO使你可以执行非阻塞IO。例如,线程可以要求通道将数据读入缓冲区。当通道将数据读入缓冲区时,线程可以执行其他操作。一旦数据被读入缓冲区,线程就可以继续处理它。将数据写入通道也是如此。
Java NIO:Selectors
Java NIO包含“选择器”的概念。选择器是一个可以监视多个事件通道的对象(例如:连接打开,数据到达等)。因此,单个线程可以监视多个通道的数据。
所有这些工作原理将在本系列的下一篇文章 - Java NIO概述中详细解释。
2.Java NIO概述
Java NIO包含以下核心组件:
- Channels
- Buffers
- Selectors
Java NIO有比这些更多的类和组件,但在我看来,Channel,Buffer和Selector构成了API的核心。其余的组件,如Pipe和FileLock,只是与三个核心组件一起使用的实用程序类。因此,我将在本NIO概述中关注这三个组件。其他组件在本教程其他地方的自己的文本中进行了解释。请参阅本页右上角的菜单。
Channels and Buffers
通常,NIO中的所有IO都以Channel开头。Channel(通道)有点像流。数据可以从Channel中读入Buffer,数据也可以从Buffer中写入Channel。这是一个例子:
Java NIO:通道将数据读入缓冲区,缓冲区将数据写入通道
有几个Channel和Buffer类型。以下是Java NIO中Channel的主要实现类:
- FileChannel
- DatagramChannel
- SocketChannel
- ServerSocketChannel
如你所见,这些通道涵盖UDP + TCP network IO,和file IO。
这些类也有一些有趣的接口,但为了简单起见,我会将它们排除在Java NIO概述之外。在Java NIO教程的其他文本中,将相关地解释它们。
以下是Java NIO中Buffer的核心实现列表:
- ByteBuffer
- CharBuffer
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
这些Buffer实现涵盖了你可以通过IO发送的基本数据类型:byte,short,int,long,float,double和characters。
Java NIO还有一个MappedByteBuffer与内存映射文件一起使用的内容。不过,我会把Buffer这个概括出来。
Selectors
选择器允许单个线程处理多个通道。如果你的应用程序打开了许多连接(通道),但每个连接只有较低的流量,这很方便。例如,在聊天服务器中。
以下是使用Selector处理3个Channel的线程图示:
要使用选择器,请使用它注册通道。然后你调用它的select()方法。此方法将阻塞,直到其中一个已注册的通道准备好了事件。一旦方法返回,线程就可以处理这些事件。事件的示例是传入连接,接收数据等。
3.Java NIO Channel
Java NIO Channel类似于流,但有一些差异:
- 你可以读取和写入Channels。流通常是单向的(读或写)。
- Channels可以异步读取和写入。
- Channels始终读取缓冲区或从缓冲区写入。
如上所述,你将数据从通道读取到缓冲区,并将数据从缓冲区写入通道。这是一个例子:
Channel Implementations
以下是Java NIO中最重要的Channel实现:
- FileChannel
- DatagramChannel
- SocketChannel
- ServerSocketChannel
FileChannel从文件读取数据和向文件写入数据。
DatagramChannel可以通过UDP在网络上读写数据。
SocketChannel可以通过TCP在网络上读写数据。
ServerSocketChannel允许你监听传入的TCP连接,就像Web服务器一样。对于每个传入连接,都会创建一个SocketChannel。
Basic Channel Example
这是一个使用FileChannel将一些数据读入Buffer的基本示例:
public class ExamBuffer {
public static void main(String[] args) throws IOException {
RandomAccessFile aFile = new RandomAccessFile("data.txt", "rw");
FileChannel inChannel = aFile.getChannel();
// 创建容量为48字节的缓冲区
ByteBuffer buf = ByteBuffer.allocate(48);
// 读入缓冲区
int bytesRead = inChannel.read(buf);
while (bytesRead != -1) {
// 使缓冲区做好读取准备
buf.flip();
while (buf.hasRemaining()) {
// 一次读取一个字节
System.out.print((char) buf.get());
}
// 清空缓冲区,使缓冲区准备好写入
buf.clear();
bytesRead = inChannel.read(buf);
}
aFile.close();
}
}
注意buf.flip( )调用。首先你读入一个缓冲区。然后你翻转它。然后你读出来了。我将在下一篇关于Buffer的文章中详细介绍。
【下篇】Java NIO学习教程(二)==>点击。