一、
NIO解释:NIO官方的解释是NEW I/O,意思是相对与BIO(同步阻塞I/O)来说是全新的,但是大部分人更喜欢叫他no-block I/O(同步非阻塞I/O),因为他相对于BIO的最大改变就是非阻塞的,我们知道传统的Socket下的流都是阻塞I/O,也就是客户端的一个请求对应服务端的一个线程,并且这个线程是一直阻塞的直到请求结束,对于线程这种宝贵的资源来说,如果并发量太大同时处理线程又阻塞时,那么势必会导致服务端资源耗尽,拖垮整个系统,就算我们用线程池代替传统的手动创建线程(这样避免了频繁的新建、销毁线程,因为线程创建也是消耗资源的,达到重复利用线程的目的,同时通过线程池也能控制客户端的并发数)但是这并没有解决一个请求对应一个线程的问题,所提他本质上还是BIO,此时NIO便产生了,NIO的最大改变就是改变了一请求一线程的状况,只要只要一个Selector就可以监听注册到其上的所有Channel,通过轮询准备好的Channel实现单线程处理多客户端请求;
接下来我们通过一个例子来看看BIO:这个例子就是一个client像server发送一个请求,server像client端返回当前时间;
TimeServer:
package com.ck.prefix.nio;
import java.io.IOException;
public class TimeServer {
public static void main(String[] args) throws IOException {
MultiplexerTimeServer m = new MultiplexerTimeServer(8081);
//起一个单独的线程来处理来自客户端的请求
new Thread(m,"NIO-MultiplexerTimeServer").start();
}
}
MultiplexerTimeServer:
package com.ck.prefix.nio;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Date;
import java.util.Iterator;
import java.util.Set;
public class MultiplexerTimeServer implements Runnable {
//多路复用选择器
private Selector selector;
private ServerSocketChannel serverChannel;
private volatile boolean isStop;
/**
* 初始化多路复用器,绑定接口
*
* @param port
* @throws IOException
*/
public MultiplexerTimeServer(int port) throws IOException {
//初始化多路复用器
selector = Selector.open();
//初始化ServerChannel
serverChannel = ServerSocketChannel.open();
//设置为未阻塞模式
serverChannel.configureBlocking(false);
//绑定ip、port,设置backlog
serverChannel.socket().bind(new InetSocketAddress("127.0.0.1", port), 1024);
//1、将serverChannel注册到selector上,并监听accept事件(就是客户端的connect请求)
serverChannel.register(selector, SelectionKey.OP_ACCEPT);
System.out.println("server初始化完成");
}
public void run() {
//服务端单线程一直循环监听来自客户端的请求
while (!isStop) {
try {
//延迟1s,不管有没有客户端请求都阻塞1s然后往下执行,如果不设置那么会一直阻塞直到有客户端的请求过来
selector.select(1000);
//循环取SelectionKey
Set<SelectionKey> selectionKeys = selector.selectedKeys();
Iterator<SelectionKey> it = selectionKeys.iterator();
SelectionKey key = null;
while (it.hasNext()) {
k