传统IO与NIO比较

一.什么是IO

所谓IO即input和output的缩写,是对数据的流入和流出的一种抽象,编程中很常见的一个概念。

二. 什么是流

体会一下这几个词:水流(静止的水想必没人会叫水流),物流,人流(此人流非彼人流 = =!),可以发现流的特点:动态的,可转移的,从一处到另一处的

三.java io

java为了我们调用方便,而屏蔽输入/输出源和流动细节,抽象出的用于解决数据流动问题的类体系,这就是java的io流
传统java.io包提供了诸如File的抽象,输入,输出流。交互方式是同步,阻塞;

第二,在java1.4中引入NIO框架(java.nio包),提供了Channel,Selector,Buffer等抽象,构建多路复用的,同步非阻塞IO,同时提供了更接近操作系统底层的高性能数据操作方式

第三,在Java 7中,NIO有了进一步的改进,也就是NIO 2。其引入了异步非阻塞IO方式,或者说AIO(Asynchronous IO)。异步IO基于事件和回调机制。

传统Sckoet IO的比喻图:
在这里插入图片描述
这里可以看到将系统比喻成餐厅,serverScoket监听端口就相当于大门,客人相当于scoket客户端,线程相当于服务员。这里看到传统IO是单线程的,即一个服务员只能服务一个客人。

我们首先来看传统的一段scoket编程

package OIO;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
 * 传统socket服务端
 * @author -琴兽-
 *
 */
public class OioServer {

	@SuppressWarnings("resource")
	public static void main(String[] args) throws Exception {

		ExecutorService newCachedThreadPool = Executors.newCachedThreadPool();
		//创建socket服务,监听10101端口
		ServerSocket server=new ServerSocket(10101);
		System.out.println("服务器启动!");
		while(true){
			//获取一个套接字(阻塞)
			final Socket socket = server.accept();
			System.out.println("来个一个新客户端!");
			newCachedThreadPool.execute(new Runnable() {
				
				@Override
				public void run() {
					//业务处理
					handler(socket);
				}
			});
			
		}
	}
	
	/**
	 * 读取数据
	 * @param socket
	 * @throws Exception
	 */
	public static void handler(Socket socket){
			try {
				byte[] bytes = new byte[1024];
				InputStream inputStream = socket.getInputStream();
				
				while(true){
					//读取数据(阻塞)
					int read = inputStream.read(bytes);
					if(read != -1){
						System.out.println(new String(bytes, 0, read));
					}else{
						break;
					}
				}
			} catch (Exception e) {
				e.printStackTrace();
			}finally{
				try {
					System.out.println("socket关闭");
					socket.close();
				} catch (IOException e) {
					e.printStackTrace();
				}
			}
	}
}

这里用的是线程池创建的scoket,可以解决单线程的服务器的缺点,必竟单线程情况下只能有一个客户端
但是用线程池可以有多个客户端连接,但是非常消耗性能。就比如说饭店一个服务员只能对一个顾客服务吗?

故传送IO特点:

阻塞点
server.accept();
inputStream.read(bytes);

单线程情况下只能有一个客户端


用线程池可以有多个客户端连接,但是非常消耗性能

四.什么是NIO

NIO的流程图:
在这里插入图片描述
这里看到还是将系统比喻成餐厅,ServerSocketChannel.socket相当于大门,客人相当于客户端,线程加selector相当于服务员。
与传统IO不同的是这里是一个服务员可以服务多个客人

在Java1.4之前的I/O系统中,提供的都是面向流的I/O系统,系统一次一个字节地处理数据,一个输入流产生一个字节的数据,一个输出流消费一个字节的数据,面向流的I/O速度非常慢,而在Java 1.4中推出了NIO,这是一个面向块的I/O系统,系统以块的方式处理处理,每一个操作在一步中产生或者消费一个数据库,按块处理要比按字节处理数据快的多。

NIO通过线程的轮询,实现非阻塞IO

在NIO中有几个核心对象需要掌握:缓冲区(Buffer)、通道(Channel)、选择器(Selector)。

  1. Buffer 缓冲区;高效的数据容器 ,不同的是BIO将数据直接读写到Stream对象中 NIO的数据操作都是在缓冲区中进行的 ,缓冲区实际上是一个数组,常见类型ByteBuffer,CharBuffer,ShortBuffer,IntBuffer,LongBuffer,FloutBuffer,DoubleBuffer
  2. Channel 在NIO中被用来支持批量式IO操作的一种抽象,与流不同,通道是双向的。 File/Socket,通常被认为是比较高层次的抽象,而Channel则是更加偏向操作系统底层的一种抽象,这也使得NIO得以充分利用现代操作系统底层机制,进行性能优化。分两大类:网络读写SelectableChannel(子类包括SocketChannel和ServerSocketChannel);文件操作(FileChannel)
  3. Selector 是NIO实现多路复用的基础。它提供一种高效机制,不断轮询注册在其上的Channel,找出处于就绪状态,通过SelectionKey取得就绪的Channel集合,进行后续的IO操作。服务端只要提供一个负责Selector轮询的线程即可,实现单线程对多Channel的高效管理,也是基于操作系统底层机制
  4. Charset 提供Unicode字符串定义,NIO也提供了相应的编解码等
    在这里插入图片描述

五.总结

IO,阻塞同步通信模式,客户端与服务端三次握手,简单,吞吐量小。关键词:Socket和ServerSocket;
NIO,非阻塞同步通信模式,客户端与服务端通过Channel连接,采用多路复用器轮询注册的Channel。关键词:SocketChannel和ServerSocketChannel;
AIO,非阻塞异步通信模式,基于事件和回调机制,采用异步通道实现异步通信。关键词:AsynchronousSocketChannel和AsynchronousServerSocketChannel。
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值