java BIO NIO AIO 理论篇

     java中的IO主要源自于网络和本地文件

 

     IO的方式通常分为几种,同步阻塞的BIO、同步非阻塞的NIO、异步非阻塞的AIO

     在JDK1.4出来之前,我们建立网络连接的时候采用BIO模式,需要先在服务端启动一个ServerSocket,然后在客户端启动Socket来对服务端进行通信,默认情况下服务端需要对每个请求建立一堆线程等待请求,而客户端发送请求后,先咨询服务端是否有线程相应,如果没有则会一直等待或者遭到拒绝请求,如果有的话,客户端会线程会等待请求结束后才继续执行。

 

     BIO与NIO一个比较重要的不同,是我们使用BIO的时候往往会引入多线程,每个连接一个单独的线程;而NIO则是使用单线程或者只使用少量的多线程,每个连接共用一个线程。

   

    

      NIO的最重要的地方是当一个连接创建后,不需要对应一个线程,这个连接会被注册到多路复用器上面,所以所有的连接只需要一个线程就可以搞定,当这个线程中的多路复用器进行轮询的时候,发现连接上有请求的话,才开启一个线程进行处理,也就是一个请求一个线程模式。

 

 

      在NIO的处理方式中,当一个请求来的话,开启线程进行处理,可能会等待后端应用的资源(JDBC连接等),其实这个线程就被阻塞了,当并发上来的话,还是会有BIO一样的问题。

  HTTP/1.1出现后,有了Http长连接,这样除了超时和指明特定关闭的http header外,这个链接是一直打开的状态的,这样在NIO处理中可以进一步的进化,在后端资源中可以实现资源池或者队列,当请求来的话,开启的线程把请求和请求数据传送给后端资源池或者队列里面就返回,并且在全局的地方保持住这个现场(哪个连接的哪个请求等),这样前面的线程还是可以去接受其他的请求,而后端的应用的处理只需要执行队列里面的就可以了,这样请求处理和后端应用是异步的.当后端处理完,到全局地方得到现场,产生响应,这个就实现了异步处理。

 

     BIO是一个连接一个线程。

   NIO是一个请求一个线程。

   AIO是一个有效请求一个线程。

### JavaBIONIOAIO 的区别 #### 同步阻塞 I/O (BIO) 同步阻塞 I/O 是最传统的 I/O 模型。在这种模式下,当应用程序发起一个 I/O 请求时,调用线程会被挂起直到请求完成。这意味着如果当前线程正在处理某个耗时的 I/O 操作,则该线程无法继续执行其他任务。 对于服务器端开发而言,通常需要为每一个客户端连接创建一个新的线程来处理通信过程中的读写操作。这种方式虽然简单直观,但在高并发场景下的资源消耗非常大,因为每个活跃连接都需要占用独立的工作线程[^5]。 ```java ServerSocket server = new ServerSocket(port); while(true){ Socket client = server.accept(); // 此处会发生阻塞 } ``` #### 非阻塞 I/O (NIO) 非阻塞 I/O 则允许程序在发出 I/O 调用时不被阻塞,而是立即返回给调用方。具体来说,在 NIO 下可以通过 `Selector` 对象管理多个 Channel 实例的状态变化事件(如可读、可写)。一旦有就绪状态发生改变,就会触发相应的回调逻辑去处理实际的数据交换工作。这种机制大大提高了单个线程所能承载的最大并发量,并且降低了上下文切换带来的开销[^3]。 ```java // 创建 Selector 并注册感兴趣的事件类型 Selector selector = Selector.open(); serverChannel.configureBlocking(false); serverChannel.register(selector, SelectionKey.OP_ACCEPT); // 处理已准备好的 channel int readyChannels = selector.select(); if (readyChannels == 0) continue; Set<SelectionKey> selectedKeys = selector.selectedKeys(); Iterator<SelectionKey> keyIterator = selectedKeys.iterator(); while(keyIterator.hasNext()){ SelectionKey key = keyIterator.next(); if(key.isAcceptable()) { // handle accept event... } else if (key.isReadable()) { // handle read event... } ... } ``` #### 异步非阻塞 I/O (AIO/NIO.2) 自JDK 7引入以来,AIO 提供了一个更加高级别的抽象层用于构建高效的网络服务端应用。不同于之前的两种方式,这里所有的I/O操作均采用完全异步的方式运行——既不会阻塞也不会轮询查询结果;相反地,它们会在后台由操作系统负责调度直至完成后通知用户态的应用代码。开发者只需定义好完成处理器(`CompletionHandler`)即可轻松捕获到最终的结果反馈信息[^1]. ```java AsynchronousServerSocketChannel serverChannel = AsynchronousServerSocketChannel.open(); serverChannel.bind(new InetSocketAddress(port)); serverChannel.accept(null, new CompletionHandler<AsynchronousSocketChannel, Void>() { @Override public void completed(AsynchronousSocketChannel result, Void attachment) { System.out.println("New connection accepted"); ByteBuffer buffer = ByteBuffer.allocate(BUFFER_SIZE); result.read(buffer, buffer, new ReadCompletionHandler(result)); } @Override public void failed(Throwable exc, Void attachment) { logger.log(Level.SEVERE,"Failed to accept a connection",exc); } }); ``` ### 应用场景分析 - **低并发环境**: 如果业务需求较为单一且预计访问压力不大,那么可以选择简单的 BIO 方案快速搭建原型系统; - **中等规模并发负载**: 当面对一定数量级的同时在线用户数时,建议考虑基于 NIO 构建的服务架构,利用多路复用技术提升吞吐率; - **大规模分布式集群部署**: 在追求极致性能表现的情况下,尤其是涉及到海量短链接频繁交互或是长时间保持长连接通讯的任务场景,应该优先评估是否适合迁移到支持全异步语义的新一代 API —— 即 AIO 上面。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值