java 中io有那些模式_Java IO使用的四种模式

对于Java IO,从大的种类上来分,可以分为BIO和NIO。BIO全称为Blocked IO,也即阻塞型IO,而NIO则是在jdk 1.4中引入的,一般称其为New IO,因为这是相对于1.4版本之前的阻塞型IO而言的,但是也有人称其为Non-blocked IO。相对而言,本人更喜欢第二种叫法,因为从字面上更符合其使用含义。本文则主要基于BIO和NIO讲解四种IO模式的基本使用方式,并且对这四种模式的优缺点进行对比。

最基本的BIO使用方式就是同步SocketChannel的方式,我们这里以经典的EchoClient/EchoServer模式来对其进行讲解,如下是一个示例:

这里可以看到,服务端处理主要是首先开启一个ServerSocketChannel,然后在一个无限循环中不断获取客户端连接,获取之后进行处理,并且写入响应信息。下面我们看看客户端代码:

如下分别是服务端和客户端打印的数据:

可以看到,服务端和客户端都正常接收并且处理了对方的数据。关于同步BIO模式,这里主要存在以下几个问题:

上述BIO模式中,最主要的问题在于服务器同一时刻只能处理一个客户端请求,这会极大的限制服务器性能。这里可以采用异步BIO的模式解决这个问题,也就是上面的服务器主线程只负责接收客户端请求,在收到请求之后将客户端请求Channel委托到一个线程池中异步进行处理。这样服务器在同一时刻就可以同时建立多个连接,极大的提升了服务器的性能。如下是EchoServer的代码:

对于客户端代码,其与同步BIO模式中的一致,这里就不再赘述。可以看到,相对于同步BIO模式,异步BIO模式改进了其主要问题,因而可以在同一时刻接收到多个客户端请求。但是对于异步BIO模式,其存在的问题也非常明显:

由于BIO存在的诸多问题,在jdk 1.4中,Java提供了一种非阻塞型的IO模型,也即NIO。NIO本质上采用的是IO多路复用模式,实际上就是一个事件驱动模型,简单的理解为一个服务器在绑定某个端口之后,其可以在一个线程了同时监听多个客户端连接,而且服务器可以对每个客户端分别设置对其哪些事件感兴趣。当客户端有对应的事件发生时,其就会通知服务器监听线程,服务器线程监听到对应的事件之后,其就会将其交由线程池处理对应的事件。实际上,Java的NIO模式在底层也是依赖于操作系统的多路复用模型,对于Linux系统,其底层是使用epoll模型实现的,而对于Mac os,其则是使用kqueue模型实现的。如下是一个IO多路复用的示意图:

对于Java IO,从大的种类上来分,可以分为BIO和NIO。BIO全称为Blocked IO,也即阻塞型IO,而NIO则是在jdk 1.4中引入的,一般称其为New IO,因为这是相对于1.4版本之前的阻塞型IO而言的,但是也有人称其为Non-blocked IO。相对而言,本人更喜欢第二种叫法,因为从字面上更符合其使用含义。本文则主要基于BIO和NIO讲解四种IO模式的基本使用方式,并且对这四种模式的优缺点进行对比。

最基本的BIO使用方式就是同步SocketChannel的方式,我们这里以经典的EchoClient/EchoServer模式来对其进行讲解,如下是一个示例:

这里可以看到,服务端处理主要是首先开启一个ServerSocketChannel,然后在一个无限循环中不断获取客户端连接,获取之后进行处理,并且写入响应信息。下面我们看看客户端代码:

如下分别是服务端和客户端打印的数据:

可以看到,服务端和客户端都正常接收并且处理了对方的数据。关于同步BIO模式,这里主要存在以下几个问题:

上述BIO模式中,最主要的问题在于服务器同一时刻只能处理一个客户端请求,这会极大的限制服务器性能。这里可以采用异步BIO的模式解决这个问题,也就是上面的服务器主线程只负责接收客户端请求,在收到请求之后将客户端请求Channel委托到一个线程池中异步进行处理。这样服务器在同一时刻就可以同时建立多个连接,极大的提升了服务器的性能。如下是EchoServer的代码:

对于客户端代码,其与同步BIO模式中的一致,这里就不再赘述。可以看到,相对于同步BIO模式,异步BIO模式改进了其主要问题,因而可以在同一时刻接收到多个客户端请求。但是对于异步BIO模式,其存在的问题也非常明显:

由于BIO存在的诸多问题,在jdk 1.4中,Java提供了一种非阻塞型的IO模型,也即NIO。NIO本质上采用的是IO多路复用模式,实际上就是一个事件驱动模型,简单的理解为一个服务器在绑定某个端口之后,其可以在一个线程了同时监听多个客户端连接,而且服务器可以对每个客户端分别设置对其哪些事件感兴趣。当客户端有对应的事件发生时,其就会通知服务器监听线程,服务器线程监听到对应的事件之后,其就会将其交由线程池处理对应的事件。实际上,Java的NIO模式在底层也是依赖于操作系统的多路复用模型,对于Linux系统,其底层是使用epoll模型实现的,而对于Mac os,其则是使用kqueue模型实现的。如下是一个IO多路复用的示意图:

对于Java IO,从大的种类上来分,可以分为BIO和NIO。BIO全称为Blocked IO,也即阻塞型IO,而NIO则是在jdk 1.4中引入的,一般称其为New IO,因为这是相对于1.4版本之前的阻塞型IO而言的,但是也有人称其为Non-blocked IO。相对而言,本人更喜欢第二种叫法,因为从字面上更符合其使用含义。本文则主要基于BIO和NIO讲解四种IO模式的基本使用方式,并且对这四种模式的优缺点进行对比。

最基本的BIO使用方式就是同步SocketChannel的方式,我们这里以经典的EchoClient/EchoServer模式来对其进行讲解,如下是一个示例:

这里可以看到,服务端处理主要是首先开启一个ServerSocketChannel,然后在一个无限循环中不断获取客户端连接,获取之后进行处理,并且写入响应信息。下面我们看看客户端代码:

如下分别是服务端和客户端打印的数据:

可以看到,服务端和客户端都正常接收并且处理了对方的数据。关于同步BIO模式,这里主要存在以下几个问题:

上述BIO模式中,最主要的问题在于服务器同一时刻只能处理一个客户端请求,这会极大的限制服务器性能。这里可以采用异步BIO的模式解决这个问题,也就是上面的服务器主线程只负责接收客户端请求,在收到请求之后将客户端请求Channel委托到一个线程池中异步进行处理。这样服务器在同一时刻就可以同时建立多个连接,极大的提升了服务器的性能。如下是EchoServer的代码:

对于客户端代码,其与同步BIO模式中的一致,这里就不再赘述。可以看到,相对于同步BIO模式,异步BIO模式改进了其主要问题,因而可以在同一时刻接收到多个客户端请求。但是对于异步BIO模式,其存在的问题也非常明显:

由于BIO存在的诸多问题,在jdk 1.4中,Java提供了一种非阻塞型的IO模型,也即NIO。NIO本质上采用的是IO多路复用模式,实际上就是一个事件驱动模型,简单的理解为一个服务器在绑定某个端口之后,其可以在一个线程了同时监听多个客户端连接,而且服务器可以对每个客户端分别设置对其哪些事件感兴趣。当客户端有对应的事件发生时,其就会通知服务器监听线程,服务器线程监听到对应的事件之后,其就会将其交由线程池处理对应的事件。实际上,Java的NIO模式在底层也是依赖于操作系统的多路复用模型,对于Linux系统,其底层是使用epoll模型实现的,而对于Mac os,其则是使用kqueue模型实现的。如下是一个IO多路复用的示意图:

这里的Selector就可以理解为一个多路复用器,每个客户端连接就是一个SocketChannel,这些SocketChannel会在Selector上注册,并且设置对各个Channel感兴趣的事件。当Selector监听到对应的事件之后,其就会将事件交由下层的线程处理。如下是一个使用NIO处理客户端事件的示例:

在上述代码中,我们首先创建了一个ServerSocketChannel,并且通过其*configureBlocking()*方法将其设置为非阻塞模式,设置为这种模式之后,其accept()等方法就是非阻塞的。然后我们创建了一个Selector多路复用器,并且将ServerSocketChannel注册到该多路复用器上。接着通过多路复用器的select()方法阻塞当前线程,等待注册的Channel事件触发。在触发之后通过遍历SelectionKey对象来进行不同事件的处理。下面我们来看看使用Java NIO来实现客户端的代码:

这里客户端的处理模式与服务端基本类似,只是客户端首先监听的是Connect事件;在连接成功后切换为监听写入事件,以写入数据发送到服务端;在发送完成后,又会切换为监听读取事件,以等待服务器发送数据并且进行处理。这里NIO模式相对于BIO主要有以下几个优点:

对于AIO模式,其是在jdk 1.7中加入的,主要原因是NIO模式代码编写非常复杂,并且容易出错。AIO本质上还是使用的NIO的多路复用来实现的,只不过在模型上其使用的是一种事件回调的方式处理各个事件,这种方式更加符合NIO异步模型的概念,并且在编码难易程度上比NIO要小很多。

在AIO中,所有的操作都是异步执行的,而每个事件都是通过一个回调函数来进行的,这里也就是一个CompletionHandler对象。这里我们以EchoClient和EchoServer为例看一下AIO模式的使用方式:

对于上述的AIO模式服务端的代码编写,可以看出来,AIO模式完全是基于异步线程池处理客户端事件的,而且对于每个事件的处理,其都是通过一个CompletionHandler进行处理的。对于服务端而言,其首先通过AcceptCompletionHandler处理的是accept事件,处理完成之后就监听客户端的read事件,然后通过ReadCompletionHandler处理客户端的数据读入事件;最后通过一个内部类(本质上也是一个CompletionHandler)往客户端写入数据。下面我们看一下客户端代码:

可以看到,客户端的处理方式与服务端基本类似,首先是连接服务器。连接完成后,通过ConnectionCompletionHandler进行后续处理,这里首先是异步往服务器写入数据,写入完成后监听服务器的数据响应,最后读取服务器数据并打印。可以看到AIO模式相较于NIO有如下优点:

本文主要基于BIO和NIO讲解了Java IO的四种编码模式,并且循序渐进讲解了每种编码模式的基本使用方式和优缺点。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值