您的位置 首页 java

Java网络编程学习-IO模型

常规的 io 流程(这里主要讲的是网络IO)主要是以下步骤

1.操作系统得到应用程序发出的指令执行read函数,命令网卡读取数据

2. 网卡 得到数据后,将数据发送到内核空间

3.内核把数据从内核空间拷贝到用户空间

不同的IO模型都是基于上述步骤在不同的细节点作出优化,一步一步演化而来的

目前Java语言主要实现以下三种IO模型

  • Blocking IO
  • Non-Blocking IO
  • Asynchronous IO

Blocking IO

阻塞IO是最传统的一种 IO 模型,常见的阻塞IO的例子如下:

1.阻塞等待连接

 server socket .accept();  

当serverSocket执行到这里的时候,会阻塞着等待一个新的连接到来。有新连接建立,程序才会接着往下走。这就意味着当大量连接并发到来时,服务器并不能快速地接收这些连接,会出现大量客户端在合理的超时时间内不能成功连接到服务器的问题。

2.阻塞等待数据

  inputStream .readLine();  

socket的inputStream会阻塞的等待数据的就绪,当数据就绪之后,内核才会执行数据拷贝到用户空间,这个拷贝的过程也可以认为是阻塞点。这里的问题是等待数据就绪的过程,用户线程是阻塞的,一个连接就需要一个 线程 专门为之服务,不能做其他的事情。久而久之,大量的线程都是阻塞状态的,然而服务器的资源是有限的,也是说每一台服务器只能处理少量的io请求。另外,阻塞IO中,一般读取数据是每次从流中读取一个字节,这就等于是说io处理的速度也是不理想的。

由于上述两个阻塞点的存在,导致阻塞IO不能充分利用操作系统的多核cpu的优势。但是阻塞IO也有优势,api容易理解,编程过程比较简单。所以,阻塞IO一般常应用于连接数比较少的业务场景,例如小型的文件传输系统。

Non-Blocking IO

非阻塞IO为解决传统IO的阻塞问题,引入了事件机制和IO多路复用的模型。简而言之,有一个 Selector线程不断轮询,当有IO操作就绪就交给其他线程处理。这样就避免了 BIO 在accept和read处的阻塞,处理socket连接的吞吐量大大提升。但是,数据从内核拷贝到用户空间的过程仍然是阻塞的。并且,这种模式由于不停地轮询内核数据,稍有不慎就会导致死循环发生。 Java 自带的NIO由于编程模型比较复杂,应用场景较少。一般多数应用会采用 Netty 框架来开发高性能的网络应用,后面的文章会重点说明。

Asynchronous IO

异步IO的是理想中的完全无阻塞的IO模型。大致流程是,当一个线程发起read后立即返回,相当于给内核发送了一个信号,发送完信号后立即可以去做其他的任务。从内核的角度看,内核接受到这个信号后,开始接收数据并执行数据拷贝到用户线程。这些事情完成了之后,内核会发送一个完成的信号给刚才的线程,然后它继续执行刚才走了一半的IO流程。这整个步骤很完美地实现了无阻塞IO,然而由于操作系统底层对AIO的支持还不完善,导致现在AIO的应用场景依然不多。

文章来源:智云一二三科技

文章标题:Java网络编程学习-IO模型

文章地址:https://www.zhihuclub.com/188369.shtml

关于作者: 智云科技

热门文章

发表回复

您的电子邮箱地址不会被公开。

网站地图