目录
1.简介
java NIO(Non-blocking IO,非阻塞IO),本质是多路复用,以此提高服务端的并发和吞吐量。 多路复用是一个选择器Selector可以监听多个通道Channel的多种事件,如下图所示。
核心概念包括 Selector(选择器)、 Channel(通道)、Buffer(缓冲区),如读、写、Accept事件等。下面我们通过一个最简单的TCP服务端实现的demo讲解下NIO的这些组件一般用法。
Channels通道 |
与Socket等支持非阻塞IO的连接 |
Buffers缓冲 |
可由Channel通道直接读取或写入的类数组对象 |
Selectors |
指示Channel通道有IO事件 |
SelectionKeys |
维护IO事件状态和绑定 |
2.最简demo使用
用nio写个最简单的TCPServer,客户端可以连接服务端,以echo打头的指令可以响应回响,否则响应BAD_REQUEST,效果如图所示
2.1 网络线程模型图
为实现上面的服务效果,设计demo使用主线程接收客户端连接,用ThreadPoolExecutor线程池做异步IO处理。
![]() |
|
2.2 demo代码
public class EchoServer {
private static ExecutorService executor; // 用于异步读写的线程池
static {
executor = new ThreadPoolExecutor(5, 10, 10, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1000));
}
public static void main(String[] args) throws IOException {
ServerSocketChannel ssc = ServerSocketChannel.open();// 静态工厂创建服务通道
ssc.socket().bind(new InetSocketAddress(8888));
ssc.configureBlocking(false); // !!一定要
Selector selector = Selector.open(); // 静态工厂模式
ssc.register(selector, ssc.validOps()); // 注册该服务通道的Accept操作
while (true) { // 在选择器上轮询
int readyCount = selector.select(1000);
if(readyCount==0){
continue;
}
Set<SelectionKey> selectionKeys = selector.selectedKeys(); // 就绪的事件
Iterator<SelectionKey> keyIterator = selectionKeys.iterator();
while(keyIterator.hasNext()){
SelectionKey selectionKey = keyIterator.next();
if(selectionKey.isValid()){
// ServerSocketChannel有连接事件
if(selectionKey.isAcceptable()){
ServerSocketChannel server = (ServerSocketChannel) selectionKey.channel(); // key与通道关联
SocketChannel socketChannel = server.accept(); // 接收连接,获得传输通道
socketChannel.configureBlocking(false);