1.先看官方解释
Java NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式。
Java NIO: Channels and Buffers(通道和缓冲区)
标准的IO基于字节流和字符流进行操作的,而NIO是基于通道(Channel)和缓冲区(Buffer)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。
Java NIO: Non-blocking IO(非阻塞IO)
Java NIO可以让你非阻塞的使用IO,例如:当线程从通道读取数据到缓冲区时,线程还是可以进行其他事情。当数据被写入到缓冲区时,线程可以继续处理它。从缓冲区写入通道也类似。
Java NIO: Selectors(选择器)
Java NIO引入了选择器的概念,选择器用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个的线程可以监听多个数据通道。
2.自己简单理解
首先它改善了我们传统阻塞io的缺点,使用一个叫多路复用器(selector)的纽带,通过socketchannel与serversocketchannel 通道进行通信,这样就使得我们通过单线程(selector )来分发处理多客户端请求,减少资源占有,同时提供了异步处理方式提高效率。理解图如下,
简单代码:
package com.cai.nioservice;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
public class NioService {
//声明全局的多路复用器
private Selector selector;
//初始化服务器端信息
public void initNioServer() throws Exception {
//创建服务通道
ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
//设置异步
serverSocketChannel.configureBlocking(false);
//绑定一个通道
serverSocketChannel.socket().bind(new InetSocketAddress(8000));
//使用多路复用器接受客户端请求
this.selector=selector.open();
//使用多路复用器与socketchannel创建联系
serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);//注册接受状态
}
/**
* 复写监听事件
* @throws Exception
*/
public void listen() throws Exception {
System.err.println("服务器端启动。。。。。。");
//使用for循环处理监听到的socketchannel 状态
while(true) {
//获取多路复用器中注册的socketchannel事件状态
//当注册的事件到达时,方法返回;否则,该方法会一直阻塞
selector.select();
Iterator<SelectionKey> keys= this.selector.selectedKeys().iterator();
while(keys.hasNext()) {
SelectionKey key=keys.next();//获取数据交换 的通道标识
//首先移除之前处理过的key,防止事件重复处理
keys.remove();
handle(key);
}
}
}
//处理监听到的事件
public void handle(SelectionKey key) throws Exception {
//判断监听状态
if(key.isAcceptable()) {
handleAccept(key);
}else if(key.isConnectable()) {
handleConnect(key);
}else if(key.isReadable()) {
handleRead(key);
}
}
private void handleRead(SelectionKey key) throws Exception {
SocketChannel socketChannel = (SocketChannel)key.channel();
//创建读取缓冲区大小
ByteBuffer buffer = ByteBuffer.allocate(1024);
int read = socketChannel.read(buffer);
if(read > 0) {
byte[] bytes =buffer.array();
String s = new String(bytes);
System.err.println("接受消息为 : " + s);
ByteBuffer outBuffer = ByteBuffer.wrap("接受到了啊".getBytes());
socketChannel.write(outBuffer);// 将消息回送给客户端
}else {
System.err.println("关闭链接");
key.cancel();
}
}
private void handleConnect(SelectionKey key) {
System.err.println("链接成功!");
}
private void handleAccept(SelectionKey key) throws Exception {
//客户端请求
//通过key获取与客户端对接的通道
ServerSocketChannel server = (ServerSocketChannel)key.channel();
//通过服务端通道获取与客户端对用channel
SocketChannel socketChannel = server.accept();
//设置非阻塞
socketChannel.configureBlocking(false);
//改变通道状态,由接受改为可处理读取状态
socketChannel.register(selector, SelectionKey.OP_READ);
}
public static void main(String[] args) throws Exception {
NioService service = new NioService();
service.initNioServer();
service.listen();
}
}