java IO模型(BIO,NIO,AIO)

Posted PacosonSWJTU

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java IO模型(BIO,NIO,AIO)相关的知识,希望对你有一定的参考价值。

【README】

本文介绍了 3种 java io模型,包括 BIO,NIO, AIO;

IO模型名称

描述

工作原理

BIO-Blocking IO

同步并阻塞式IO

一个服务器线程处理一个客户端连接

NIO-Non-blocking IO

同步非阻塞式IO

一个服务器线程处理多个客户端连接,使用io多路复用(选择器);

AIO-Asynchronous IO

异步非阻塞式IO


【1】应用场景

  • 1)BIO方式:适用于连接数目比较小且固定的架构,这种方式对服务器资源要求比较高,并发局限于应用中,JDK1.4以前的唯一选择,但程序简单易理解。
  • 2)NIO方式:适用于连接数目多且连接比较短(轻操作)的架构,比如聊天服务器,弹幕系统,服务器间通讯等。编程比较复杂,JDK1.4开始支持。 (Netty是基于NIO的)
  • 3) AIO方式:适用于连接数目多且连接比较长(重操作)的架构,比如相册服务器,充分调用OS参与并发操作,编程比较复杂,JDK7开始支持。(不常用)

【1.1】BIO代码实现

1)服务端:

/**
 * @Description 阻塞式IO服务器
 * @author xiao tang
 * @version 1.0.0
 * @createTime 2022年08月13日
 */
public class Bioserver 
    public static void main(String[] args) throws IOException 
        // 创建一个线程池
        ExecutorService threadPool = Executors.newCachedThreadPool();
        int order = 0;

        // 创建 服务器 套接字
        ServerSocket serverSocket = new ServerSocket(6666);
        System.out.println("服务器启动成功.");
        while(true) 
            System.out.println("等待客户端请求");
            Socket socket = serverSocket.accept(); // 没有客户端请求,accept阻塞
            System.out.printf("客户端[%d]请求建立连接\\n", ++order);
            final int orderCopy = order;
            threadPool.execute(()->
                handler(socket, orderCopy);
            );
        
    

    /**
     * @description 与客户端通讯
     * @param socket 连接套接字
     * @author xiao tang
     * @date 2022/8/13
     */
    public static void handler(Socket socket, int order) 
        byte[] byteArr = new byte[1024];

        try 
            // 读取客户端发送的数据
            InputStream inputStream = socket.getInputStream();
            int length = 0;
            // 客户端没有数据,read阻塞
//            while( ( length = inputStream.read(byteArr))!= -1) 
//                System.out.println(new String(byteArr, 0, length));
//            
            while(true) 
                System.out.printf("线程id[%s],等待客户端[%d]发送数据\\n", Thread.currentThread().getId(), order);
                length = inputStream.read(byteArr);
                if (length == -1) break;
                System.out.printf("线程id[%s],客户端[%d]:" + new String(byteArr, 0, length) + "\\n",  Thread.currentThread().getId(), order);
            
         catch (IOException e) 
            e.printStackTrace();
         finally 
            // 关闭与客户端的连接
            try 
                socket.close();
                System.out.printf("关闭与客户端[%d]的连接\\n", order);
             catch (IOException e) 
            
        
    

2)客户端 :采用 win10的命令行 telnet 进程;

  • 命令行录入  telnet 127.0.0.1 6666
  • 录入 ctrl + ] 进入telnet命令行界面
  • send hello100 就把hello100 发送给服务器

发送过程如下:

 【小结】

  • 显然,在BIO-阻塞式IO模式下,服务器的一个线程处理一个客户端请求;且存在阻塞情况,在客户端数量过多的情况下,性能不高(因为客户端一直挂起,则过多的服务器线程会一直阻塞,浪费大量cpu和内存资源
  • serverSocket.accept() 在没有客户端请求时,会阻塞
  • inputStream.read(...) 在客户端没有发送数据时,会阻塞

以上是关于java IO模型(BIO,NIO,AIO)的主要内容,如果未能解决你的问题,请参考以下文章

BIO | NIO | AIO (Java版)

Java的BIO,NIO和AIO的区别于演进

从底层入手,图解 Java NIO BIO MIO AIO 四大IO模型与原理

JAVA-IO模型(BIO,NIO,AIO)

Java BIO,NIO,AIO

Netty系列:基础篇 BIO-NIO-AIO