java中的IO
传统的IO
我们通常所说的传统IO编程就是同步阻塞式的I/O编程,也就是一个Socket和一个Client的端到端的通信过程,我们启动Socket端的时候,Socket会调用accept()方法进行阻塞,等待Client端的请求,直到Client端发送请求过来,然后给于反馈。
后来发展出伪异步的I/O编程,也就是把IO编程里面加上一个自定义的线程池,这样就可以实现多个Client端的请求然后通过线程池的阻塞让Socket端一一给于请求反馈。
基础的Socket和Client代码我在这里就不进行写入了。
伪异步IO
那传统的这种IO,有了多少个Client端就要创建多少个线程去访问Socket,在jdk1.5之前没有NIO的时候,就是用的伪异步的IO来解决这个问题的。在伪异步IO这种解决方案中就是在传统的Socket中加了一个自定义线程池(可以去我自定义线程池的那篇博客去学习自定义线程池),然后像这个线程池中传入最大线程数,和BlockingQueue的容量,这样我们多个Client端访问我们Socket的时候就会在这个自定义线程池中进行阻塞。这样就会使得应用程序更加的可控,不至于使服务器被Client端撑爆。当然这种代码已经是很古老的一种代码。
JDK1.5的NIO1.0
那我们现在所说的异步非阻塞的编程到底是什么意思?
其实对于异步非阻塞真正的实现是在jdk1.7以后才真正的实现的。也就是NIO2.0的时候才实现,那么在NIO1.0的时候也就是JDK1.5的时候我们只是实现了非阻塞并没有实现异步的概念。
传统IO和NIO的区别
其实传统的IO和NIO的区别其本质就是阻塞和非阻塞的区别
阻塞概念:应用程序在获取网络数据的时候,如果网络传输很慢,那么程序就会一直处于等待状态,直到数据传输结束为止。
非阻塞概念:应用程序直接可以获取已经准备好的网络数据,无需等待。
io为同步阻塞的形式nio为同步非阻塞的形式。NIO1.0并没有实现异步的概念,在jdk1.7之后的NIO2.0才真正的实现了异步非阻塞的概念。
同步时:应用程序会直接参与IO读写操作,并且我们的程序会直接阻塞到某一个方法上,直到数据准备就绪。或者采用轮询的策略实时检查数据的就绪状态,如果就绪则获取数据。
异步时:就是所用IO操作交给操作系统处理,我们编写的应用程序不参与IO的操作,我们的程序不需要关心IO的读写,当操作系统完成了IO的读写操作时,会给我们的应用程序发送通知,我们的应用程序直接拿走数据即可。
同步说的是你的server服务器端的执行方式。
NIO编程介绍
有的人叫NIO为 New IO,而我们通常认为NIO是 Not Blocking IO,即非阻塞的IO。
学习NIO编程,我们首先要了解几个概念。
Buffer(缓冲区):在基本IO操作中,所有的数据都是以流的形式操作的,而在NIO中,则都是使用缓冲区,所有的读写操作都是使用缓冲区完成的。缓冲区本质上是一块可以写入数据,然后可以从中读取数据的内存。这块内存被包装成NIO Buffer对象,并提供了一组方法,用来方便的访问该块内存。
Channel(管道,通道):是一个TCP连接之间的抽象,一个Tcp连接可以对应多个Channel,而不是以前的方式只有一个通信信道,这个时候就减少TCP了连接的次数。
Selector(选择器,多路复用器):轮询所有的注册通道,根据通道状态执行相关操作。状态包括:Connect,Accept,Read,Write。
在server端会创建一个Selector多路复用器,所有的客户端想和服务器建立连接都要创建一个SocketChannel注册到Selector上,然后Selector使用一个线程轮询着检测所有的注册的SocketChannel的状态,根据每个不同的通道的状态执行相关的代码。NIO的本质就是避免原始的TCP建立连接使用三次握手的操作,减少连接的开销。
AIO编程介绍
服务端:AsynchronousServerSocketChannel
客户端:AsynchronousSocketChannel
用户处理器:CompletionHandler接口,这个接口实现应用程序向操作系统发起io请求。当完成后处理具体的逻辑。否则做自己该做的事情。