`

Java NIO概述及要点摘录

阅读更多

#普通IO与NIO区别?

IO:按流处理数据,速度慢;普通IO;
NIO:按块处理数据,速度快;通过通道channel和缓冲区buffer作为基础的面向块的IO处理;

#通道channel和缓冲区buffer是什么?
通道和缓冲区是NIO的核心对象;
channel是对原有IO包中流的模拟,到任何目的地的数据都需要通过channel对象;字节
buffer是一个容器对象,发送给一个channel的所有对象都必须首先放到buffer中,同样,从channel中读取的数据都要读到buffer中,是不能直接从channel中读取数据的,只能通过buffer;
buffer是一个数据,常用的是字节数组ByteBuffer,缓冲区还提供了对数据的结构化访问,可以跟踪系统的读写进程;

#通道channel是对旧的IO流的模拟,那么通道与旧的io流的区别在哪里?
channel是双向的,可以同时读写,unix底层操作系统通道也是双向的;
旧的IO流是单向的;

#NIO的文件读写
读取文件步骤:从FileInputStream获取channel,创建Buffer,将数据从channel读到buffer中;
读文件:

FileInputStream fin = new FileInputStream("demo.txt");
FileChannel fc = fin.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
fc.read(buffer);

 

 写文件:

FileOutputStream fout = new FileOutputStream("demo.txt");
FileChannel fc - fout.getChannel();
ByteBuffer buffer = ByteBuffer.allocate(1024);
for(int i=0; i< message.length; i++){
	buffer.put(message[i]);
}
buffer.flip();
fc.write(buffer);

#NIO读写时,我们不需要告诉通道要读多少数据到缓冲区中,每一个缓冲区都有复杂的内部统计机制,它会跟踪已经读了多少数据及还有多少空间可以容纳更多的数据,JDK中是如何设计和实现这个个机制的?(待深入研究.)

 

#缓冲区内部实现机制
缓冲区的两个重要实现组件:状态变量,访问方法;
每一种java基本类型的缓冲区都是对象类Buffer的子类;buffer有三个似有属性:
private int position = 0;//跟踪了向缓冲区中写入多少数据或者从缓冲区中读取了多少数据;
private int limit;//表明还有多少数据需要取出,或还有多少空间可以放入数据;
private int capacity;//该缓冲区的最大数据容量;
每个基本类型的缓冲区底层实上就是一个该类型的数组;例如ByteBuffer中的final byte[] nb;
从通道读取数据,实际上是将读取的数据放到该数组中,向通道中写入时,是将该数组中的数据写入到通道中;
#如何使用
使用缓冲区将数据从输入通道拷贝到输出通道:

while(true){
	buffer.clear();
	int r = fcin.read(buffer);
	if(r==-1){
		break;
	}
	buffer.flip();
	fcout.write(buffer);
}

 其中:clear(),flip()用于让缓冲区在读写之间切换;

 

#连网与异步IO
nio中的连网与nio中的其它操作无区别,仍然是依赖于通道和缓冲区,使用InputStream和OutputStream获取通道;
异步io调用不会阻塞。它的最大优势:允许同时根据大量的输入和输出执行IO,同步程序常常求助于轮询或者创建许多线程处理大量连接,使用异步IO,可以监听任何数量的通道上的事件,不用轮询,也不用额外的线程;

应用实例:基于非组赛io的服务器端的处理流程,它接收网络连接并向它们回响它们可能发送的数据。

private void execute () throws IOException { // 创建一个新的选择器
	Selector selector = Selector.open();
	// 打开在每个端口上的监听,并向给定的选择器注册此通道接受客户端连接的I/O事件。 
	for (int i = 0; i < ports.length; i++) {
		// 打开服务器套接字通道
		ServerSocketChannel ssc = ServerSocketChannel.open(); // 设置此通道为非阻塞模式
		ssc.configureBlocking(false);
		// 绑定到特定地址
		ServerSocket ss = ssc.socket();
		InetSocketAddress address = new InetSocketAddress(ports[i]); ss.bind(address);
		// 向给定的选择器注册此通道的接受连接事件 
		ssc.register(selector, SelectionKey.OP_ACCEPT); 
		System.out.println("Going to listen on " + ports[i]);
	}
	while (true) {
		// 这个方法会阻塞,直到至少有一个已注册的事件发生。
		// 当一个或者更多的事件发生时,此方法将返回所发生的事件的数量。 int num = selector.select();
		// 迭代所有的选择键,以处理特定的I/O事件。
		Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator<SelectionKey> iter = selectionKeys.iterator();
    	SocketChannel sc;
    	while (iter.hasNext()) {
        	SelectionKey key = iter.next();
		if ((key.readyOps() & SelectionKey.OP_ACCEPT) == SelectionKey.OP_ACCEPT) { 
			// 接受服务器套接字撒很能够传入的新的连接,并处理接受连接事件。 
			ServerSocketChannel ssc = (ServerSocketChannel) key.channel();
			sc = ssc.accept();
			// 将新连接的套接字通道设置为非阻塞模式 
			sc.configureBlocking(false);
			// 接受连接后,在此通道上从新注册读取事件,以便接收数据。 
			sc.register(selector, SelectionKey.OP_READ);
			// 删除处理过的选择键
			iter.remove();
	            	System.out.println("Got connection from " + sc);
        	} else if ((key.readyOps() & SelectionKey.OP_READ) == SelectionKey.OP_READ) {
			// 处理读取事件,读取套接字通道中发来的数据。 
			sc = (SocketChannel) key.channel();
			// 读取数据
			int bytesEchoed = 0; 
			while (true) {
	                    echoBuffer.clear();
	                    int r = sc.read(echoBuffer);
	                    if (r == -1) {
	                        break;
			}
	                echoBuffer.flip();
	                sc.write(echoBuffer);
	                bytesEchoed += r;
	       }
	      System.out.println("Echoed " + bytesEchoed + " from " + sc); // 删除处理过的选择键
	      iter.remove();
	} 
    }
  } 
}

 

 #使用allocate()分配缓冲区

ByteBuffer buffer = ByteBuffer.allocate(1024);

 其中,allocate()方法分配一个具有指定大小的底层数组,同时包装到一个对象中,例如ByteBuffer;

 

#使用数组转换成缓冲区

byte array[] = new byte[1024];
ByteBuffer buffer = ByteBuffer.wrap(array);

 #缓冲区如何分片

 

实际上就是创建一个子缓冲区,新旧缓冲区的一部分共享数据;

ByteBuffer buffer = ByteBuffer.allocate(10);
for(int i=0; i<buffer.capacity(); i++){
	buffer.put((byte)i):
}
//分片
buffer.position(3);
buffer.limit(7);
ByteBuffer slice = buffer.slice();

 #如何创建只读缓冲区,及作用?

 

调用缓冲区的asReadOnlyBuffer()方法,将缓冲区转化为只读,只读缓冲区可以保护数据,使数据不被修改;

#直接和间接缓冲区
#内存映射文件IO

#将文件的前1024个字节映射到内存

MappedByteBuffer mbf = fc.map(FileChannel.MapModel.READ_WRITE, 0 , 1024);
<pre>
#分散,聚集IO 
读:
 <pre lang="java">
long read(ByeteBuffer[] dst);
long read(ByteBuffer[] dst, in offset, int length);

 

 写:

long write(ByeteBuffer[] dst);
long write(ByteBuffer[] dst, in offset, int length);

 

 

参考:《NIO学习总结.pdf》

分享到:
评论

相关推荐

    JavaNIO chm帮助文档

    Java NIO系列教程(一) Java NIO 概述 Java NIO系列教程(二) Channel Java NIO系列教程(三) Buffer Java NIO系列教程(四) Scatter/Gather Java NIO系列教程(五) 通道之间的数据传输 Java NIO系列教程(六)...

    Java NIO系列教程(一) Java NIO 概述

    ### Java NIO 系列教程(一):Java NIO 概述 #### 一、引言 Java NIO(New IO)是Java SE 1.4版本引入的一个新的I/O处理框架,它提供了比传统Java IO包更高效的数据处理方式。NIO的核心在于其三大组件:Channels...

    java NIO和java并发编程的书籍

    java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java...

    java NIO技巧及原理

    Java NIO(New Input/Output)是Java标准库提供的一种I/O模型,它与传统的 Blocking I/O(IO)相比,提供了更加高效的数据传输方式。在Java NIO中,"新"主要体现在非阻塞和多路复用这两个特性上,这使得NIO更适合于...

    java NIO.zip

    Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java标准库提供的一种替代传统的I/O模型的新技术。自Java 1.4版本引入NIO后,它为Java开发者提供了更高效的数据传输方式,尤其是在处理大量并发...

    Java NIO英文高清原版

    Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java平台中用于替代标准I/O(BIO)模型的一种新机制。NIO在Java 1.4版本引入,提供了更高效的数据处理和通道通信方式,特别适用于高并发、大数据...

    Java NIO 中文 Java NIO 中文 Java NIO 中文文档

    Java NIO 深入探讨了 1.4 版的 I/O 新特性,并告诉您如何使用这些特性来极大地提升您所写的 Java 代码的执行效率。这本小册子就程序员所面临的有代表性的 I/O 问题作了详尽阐述,并讲解了 如何才能充分利用新的 I/O ...

    java NIO 视频教程

    Java NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式。 Java NIO: Channels and Buffers(通道和缓冲区) 标准的IO基于字节流和字符流进行操作的,...

    java nio 包读取超大数据文件

    ### Java NIO 处理超大数据文件的知识点详解 #### 一、Java NIO简介 Java NIO(New IO)是Java平台上的新输入/输出流API,它提供了与传统IO(即Java IO)不同的数据处理方式。NIO在Java 1.4版本引入,并在后续版本...

    Java NIO详解及源码下载

    Java NIO(New IO)是Java 1.4版本引入的一个新模块,全称为Non-blocking Input/Output,它提供了一种不同于传统IO的编程模型,传统IO基于块I/O(Blocking I/O),而NIO则基于通道(Channels)和缓冲区(Buffers)...

    java NIO实例

    Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java从1.4版本开始引入的一种新的I/O模型,它为Java应用程序提供了更高效的数据传输方式。传统的Java I/O模型(BIO)在处理大量并发连接时效率较...

    java nio入门学习,两个pdf

    一、Java NIO概述 传统的Java I/O基于流(Stream)和缓冲区(Buffer)的模型,是阻塞式的,即在进行读写操作时会一直等待数据准备好或全部写入完成。而NIO的核心理念在于非阻塞,它允许程序在没有数据可读或可写时继续...

    一个java NIO的例子

    Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java标准库提供的一种替代传统I/O模型的新技术。在传统的Java IO模型中,读写操作是阻塞的,即当调用read或write方法时,线程会等待数据准备好或...

    Java Nio selector例程

    java侧起server(NioUdpServer1.java),基于Java Nio的selector 阻塞等候,一个android app(NioUdpClient1文件夹)和一个java程序(UI.java)作为两个client分别向该server发数据,server收到后分别打印收到的消息...

Global site tag (gtag.js) - Google Analytics