Java IO编程中的几个概念

BIO NIO AIO

java中的BIO NIO AIO 是在不同java版本更新过程中依次引入的, 性能也越来越好.
这个3个IO分别指:

  • BIO:同步阻塞IO, 传统的java.io包.
  • NIO: new IO, 是一种同步非阻塞IO, java,nio包, java 1.4引入.
  • AIO: 异步非阻塞IO, 也称NIO2, 由java 1.7引入, 应用还不是特别广泛.

阻塞 非阻塞 同步 异步

一开始接触这几个概念会感觉有些困惑, 但抓住应用程序线程, 操作系统的线程以及内存的内核空间用户空间这几个概念就好了.一个IO操作需要操作系统线程将数据准备好, 并将数据从内核空间复制到用户空间. 具体过程:首先一个IO请求由应用程序线程发起, 接着操作系统的线程会将数据在内存的内核空间将数据准备好, 然后再从内核空间拷贝至用户空间, 供应用程序的线程读取.

  1. 阻塞
    阻塞是指应用程序的线程在IO操作处阻塞, 而不能进行往下执行.
  2. 非阻塞
    非阻塞则是, 就算操作系统的线程还未将IO操作的数据准备好,应用程序的线程还能够继续汪下执行.
  3. 同步
    同步本身是指多个线程之间的同步. 在IO操作中是指应用程序的线程是指需要不断的去询问操作系统线程IO操作的数据是否准备好.
  4. 异步
    相对同步, 异步则是程序的线程不用不断询问操作系统的线程数据时候准备好, 而是一旦操作系统的线程将数据准备好准备好了, 操作系统的线程会主动通知应用程序的线程. 异步需要操作系统的内核线程给与更多的支持.

BIO NIO AIO的应用场景2

BIO NIO AIO都有自己的应用场景, BIO性能低下, 适合连接数量少, 连接小的场景;

  • BIO 方式适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中, JDK1.4以前的唯一选择,但程序简单易理解。

  • NIO 方式适用于连接数目多且连接比较短(轻操作) 的架构, 比如聊天服务器, 弹幕系统, 服务器间通讯等。编程比较复杂, JDK1.4 开始支持。

  • AIO 方式使用于连接数目多且连接比较长 (重操作) 的架构, 比如相册服务器, 充分调用 0S 参与并发操作,编程比较复杂, JDK7 开始支持。

    AIO需要更加依赖操作系统的支持, 但Linux操作系统从2.6版本才开始支持AIO, 现在还不如windos的完善, 在高并发网络编程中依然以IO复用模式为主.

NIO解读

NIO是一种单线程的多路复用IO, 其通过selector选择器监听多个连接, 一旦有连接需要处理则往下执行依次处理这些连接请求, 处理完之后再此循环至selector处查看是否有请求需要处理, 整个过程为单线程, 涉及线程切换.

虽然NIO的selector也会阻塞线程, 但是其依然叫同步非阻塞原因在于它可以同时监听多个IO操作, 在一些IO操作数据还没准备好的时候, 可以去处理其它IO操作, 并不会被某一个IO操作阻塞, 因此称为非阻塞IO, 这也是它被称为多路复用的原因.
下面是一个简单的代码示例:

public class NIOServer extends Thread {

	public void run() {
	try (Selector selector = Selector.open(); // 创建Selector
	ServerSocketChannel serverSocket = ServerSocketChannel.open();) {  // 创建服务器socket
	serverSocket.bind(new InetSocketAddress(InetAddress.getLocalHost(), 8888));// 绑定IP地址与端口
	serverSocket.configureBlocking(false);  // 将服务器socket设置为非阻塞
	
	serverSocket.register(selector, SelectionKey.OP_ACCEPT);  // 注册selector
	
	while (true) {
		selector.select();// 监测是否有连接
		
		Set<SelectionKey> selectedKeys = selector.selectedKeys();
		Iterator<SelectionKey> iter = selectedKeys.iterator();
		while (iter.hasNext()) {// 遍历处理连接
		SelectionKey key = iter.next();
		requestHandler((ServerSocketChannel) key.channel());
		iter.remove();
		}
	}
}

参考

  1. http://www.52im.net/thread-306-1-1.html
  2. https://www.bilibili.com/video/av76227904?p=4
  3. https://juejin.im/post/5bea1d2e51882523d3163657
  4. https://www.jianshu.com/p/2965fca6bb8f
原文地址:https://www.cnblogs.com/bitbitbyte/p/12536573.html