#普通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》
分享到:
相关推荐
Java NIO系列教程(一) Java NIO 概述 Java NIO系列教程(二) Channel Java NIO系列教程(三) Buffer Java NIO系列教程(四) Scatter/Gather 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...
Java NIO(New Input/Output)是Java标准库提供的一种I/O模型,它与传统的 Blocking I/O(IO)相比,提供了更加高效的数据传输方式。在Java NIO中,"新"主要体现在非阻塞和多路复用这两个特性上,这使得NIO更适合于...
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java标准库提供的一种替代传统的I/O模型的新技术。自Java 1.4版本引入NIO后,它为Java开发者提供了更高效的数据传输方式,尤其是在处理大量并发...
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java平台中用于替代标准I/O(BIO)模型的一种新机制。NIO在Java 1.4版本引入,提供了更高效的数据处理和通道通信方式,特别适用于高并发、大数据...
Java NIO 深入探讨了 1.4 版的 I/O 新特性,并告诉您如何使用这些特性来极大地提升您所写的 Java 代码的执行效率。这本小册子就程序员所面临的有代表性的 I/O 问题作了详尽阐述,并讲解了 如何才能充分利用新的 I/O ...
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(New IO)是Java平台上的新输入/输出流API,它提供了与传统IO(即Java IO)不同的数据处理方式。NIO在Java 1.4版本引入,并在后续版本...
Java NIO(New IO)是Java 1.4版本引入的一个新模块,全称为Non-blocking Input/Output,它提供了一种不同于传统IO的编程模型,传统IO基于块I/O(Blocking I/O),而NIO则基于通道(Channels)和缓冲区(Buffers)...
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java从1.4版本开始引入的一种新的I/O模型,它为Java应用程序提供了更高效的数据传输方式。传统的Java I/O模型(BIO)在处理大量并发连接时效率较...
一、Java NIO概述 传统的Java I/O基于流(Stream)和缓冲区(Buffer)的模型,是阻塞式的,即在进行读写操作时会一直等待数据准备好或全部写入完成。而NIO的核心理念在于非阻塞,它允许程序在没有数据可读或可写时继续...
### Java NIO 概述 Java NIO 是 Java 平台的一个重要特性,首次出现在 Java 1.4 版本中。它为 Java 开发者提供了一套全新的 I/O 处理方式,相比于传统的 I/O API,新版本提供了更高效、更灵活的解决方案。本书...
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java标准库提供的一种替代传统I/O模型的新技术。在传统的Java IO模型中,读写操作是阻塞的,即当调用read或write方法时,线程会等待数据准备好或...
java侧起server(NioUdpServer1.java),基于Java Nio的selector 阻塞等候,一个android app(NioUdpClient1文件夹)和一个java程序(UI.java)作为两个client分别向该server发数据,server收到后分别打印收到的消息...