NIO是什么 New IO,始于Java1.4,提供新的非阻塞 JavaIO 操作API. 又称Non-Blocking IO 非阻塞IO 替代旧版本的Blocking IO, 多用于网络相关的API.

为什么要使用NIO 使用NIO后,WEB网络程序性能可以进一步提高 模拟Tomcat7, 阻塞IO处理Http请求:

public class BIOHttpServer { public static void main(String[] args) throws IOException { ServerSocket socket = new ServerSocket(8080); System.out.println(Thread.currentThread().getName()+"启动:"+8080); while(true){ Socket accept = socket.accept(); InputStream inputStream = accept.getInputStream(); byte[] b = new byte[1024]; inputStream.read(b); System.out.println(new String(b));

			// http响应头 必须这样写:
			String response = "HTTP/1.1 200 ok\r\nContent-Length: 11\r\n\r\nHello World\r\n";
			accept.getOutputStream().write(response.getBytes());
			accept.getOutputStream().flush();
			accept.close();			
	}
}

}

NIO高性能的核心原理: 发起连接 操作系统接收连接 TCP模块 + 多路复用机制 一个Java线程通过Selector工具选择性处理 有数据传输的交给线程池 最终达到,线程最大程度利用

使用NIO:

模拟Tomcat8.5, NIO处理Http请求: public class NIOHttpServer { public static void main(String[] args) throws IOException {

	// 1.ServerSocketChannel 绑定端口
	ServerSocketChannel socket = ServerSocketChannel.open();
	socket.configureBlocking(false); // no-Blocking
	socket.bind(new InetSocketAddress(8080));

	System.out.println("NIO服务器启动,端口:"+8080);

	// 2.获取新连接 
	// selector 获取不同操作系统下不同的tcp连接动态
	Selector selector = Selector.open();
	
	// 选择器,根据条件查询符合情况地TCP连接
	socket.register(selector, SelectionKey.OP_ACCEPT);
	
	while(true){
		selector.select(1000); //如果没有新连接,就等待
		
		// 3. 处理查询结果
		Set<SelectionKey> keys = selector.selectedKeys();
		Iterator<SelectionKey> iterator = keys.iterator();

		while(iterator.hasNext()){
			SelectionKey result = iterator.next();
			
			//根据不同的类型,分别进行处理
			if(result.isAcceptable()){ //3.1 拿到新连接对象
				// nio体现,accept 不阻塞,没有连接则返回null
				SocketChannel accept = socket.accept();
				if(accept!=null){
					// 注册连接对象,进行关注
					accept.configureBlocking(false);// no-Blocking
					accept.register(selector, SelectionKey.OP_READ);
				}
			}
			if(result.isReadable()){ //3.2 有数据请求的连接
				SocketChannel channel = (SocketChannel) result.channel();
				// 处理过程中,先取消selector对应连接的注册,避免重复
				result.cancel();
				
				// NIO的读写方式: 字节缓冲区
				ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
				channel.read(byteBuffer);
				byteBuffer.flip(); //模式转换
				byte[] b = byteBuffer.array();
				String request = new String(b);
				
				//处理请求... 
				System.out.println(request);

				//数据响应:NIO的写数据
				String response = "HTTP/1.1 200 ok\r\nContent-Length: 11\r\n\r\nHello World\r\n";
				channel.write(ByteBuffer.wrap(response.getBytes()));
				
				// 处理完成,重新注册,继续接收处理新的连接
				// channel.register(selector, SelectionKey.OP_READ);
			}
			// 删除处理过的结果(事件)
			iterator.remove();
		}	
		
		// 检查过程就绪,清除之前的调用效果
		selector.selectNow();
	}
}

}

(本文章由源码时代技术老师原创,转载请注明出处!)