NIO提供全新的底层I/O模型。与最初的java.io包中面向流(stream-oriented)概念不同,NIO采用了面向块的概念(block-oriented)。在尽可能的情况下,I/O的操作以大的数据块为单位进行,而不是一次一个字节或字符。这样提高java的I/O性能,也牺牲了操作的简单性。
NIO中提供与平台无关的非阻塞I/O,与面向线程的、阻塞式I/O方式相比,多道通信、非阻塞I/O技术可以使应用程序更有效地处理大量连接的情况。
新IO没有在原来的IO基础上开发,而是采用全新的类和接口,除了原有的功能外还提供了以下特性:
1. 多路选择的非封锁式I/O设施
2. 支持文件锁和内存映射
3. 支持正则表达式的模式匹配设施
4. 字符集编码器和译码器
缓冲区与Buffer
在基本IO操作中所有的操作都是直接以流的形式完成的,而在NIO中所有的操作都要使用到缓冲区处理,且所有的读写操作都是通过缓冲区完成的。缓冲区(Buffer)是一个线性的、有序的数据集,只能容纳某种特定的数据类型。
java.nio.Buffer 是一个抽象类
public final int capacity() 返回此缓冲区的容量
public final int limit() 返回此缓冲区的限制
public final Buffer limit(int newLimit) 返回此缓冲区的限制
public final int position() 返回缓冲区的操作位置
public final Buffer position(int newPosition) 设置缓冲区的操作位置
public final Buffer clear() 清空缓冲区
public final Buffer flip() 重设缓冲区,在写入前调用,改变缓冲的指针
public final Buffer reset() 回复缓冲区中的标记位置
public final boolean hasRemaining() 判断在当前位置和限制之间是否有内容
nio中针对每一种基本数据类型都有一种对应的缓冲区操作类
java.nio.ByteBuffer
java.nio.CharBuffer
java.nio.ShortBuffer
java.nio.IntBuffer
java.nio.LongBuffer
java.nio.FloatBuffer
java.nio.DoubleBuffer
深入缓冲区操作
Buffer 中存在一系列的状态变量,这些状态变量随着写入或读取都有可能被改变。用3个值表示缓冲区的状态
position 表示下一个缓冲区读取或写入的操作指针,当向缓冲区中写入数据时此指针就会改变,指针永远放到写入的最后一个元素之后。
limit 表示还有多少个数据需要存储或读取 position<=limit
capacity 表示缓冲区的最大容量<=capacity。 值在分配缓冲区时被设置,一般不会更改
通道(Channel)
通道可以用来读取和写入数据,通道类似于之前的输入/输出流,但是程序不会直接操作通道,所有的内容都是先读到或写入到缓冲区中,再通过缓冲区中取得或写入的。
传统的流操作分输入或输出流,而通道本身是双向操作的,既可以完成输入也可以完成输出。
Channel本身是一个接口
void close() 关闭通道
boolean isOpen() 判断此通道是否是打开的
FileChannel 类
进行文件的读/写操作
public int read(ByteBuffer dst) 将内容读入到缓冲区中
public int write(ByteBuffer src) 将内容从缓冲区写入到通道
public final void close() 关闭通道
public abstract MappedByteBuffer map(FileChannel,.MapMode mode, long position, long size) 将通道的文件区域映射到内容中,同时指定映射模式、文件中的映射文件以及要映射的区域大小
要使用FileChannel,可以依靠FileInputStream或FileOutputStream类中的getChannel()方法取得输入或输出的通道。
内存映射
内存映射可以把文件映射到内存中,这样文件内的数据就可以用内存读/写指令来访问,而不是用InputStream或OutputStream这样的I/O操作类,这也是速度最快的读取文件方式。
使用FileChannel类提供的map()方法,可以将文件映射到内存中。
public abstract MappedByteBuffer map(FileChannel.MapMode mode, long position, long size)
map()方法在使用时要指定映射模式,在内存映射中提供了3种模式,此3种模式分别有FileChannel类中的3个常量表示
public static final FileChannel.MapMode READ_ONLY 只读映射模式
public static final FileChannel.MapMode Read_WRITE 读取/写入映射模式
public static final FileChannel.MapMode PRIVATE 专用(写入时复制)映射模式
文件锁:FileLock
Java 新IO中提供了文件锁的功能,这样当一个线程将文件锁定后,其他线程是无法操作此文件的。要想进行文件的锁定操作,则要使用FileLock类完成,此类的对象需要依靠FileChannel进行实例化操作。
FileChannel类中提供的实例化FileLock对象的方法
public final FileLock lock() 获得此通道文件的独占锁定
public abstract FileLock lock(long position, long size, boolean shared) 获得此通道文件给定区域的锁定,并指定锁定位置、锁定大小、是共享锁定true或独占锁定false
public final FileLock tryLock() 试图获取此通道的独占锁定
public abstract FileLock tryLock(long position, long size, boolean shared) 试图获取此通道指定区域的锁定,并指定锁定位置、锁定大小,属于共享锁定或独占锁定
共享锁:允许多个线程进行文件的读取操作
独占锁:只允许一个线程进行文件的读/写操作
文件锁定后需要依靠FileLock类进行解锁,FileLock类的常用方法:
public final boolean isShared() 判断锁定是否为共享锁定
public final FileChannel channel() 返回此锁定的FileChannel
public abstract void release() 释放锁定(解锁)
public final long size() 返回锁定区域的大小
Charset 字符集
负责处理编码的问题,包含了创建编码器(CharsetEncoder)和创建解码器(CharsetDecoder)的操作
Selector
在原来使用IO和Socket构造网络服务时,所有的网络服务将使用阻塞的方式进行客户端的连接,而如果使用新IO则可以构造一个非阻塞的网络服务。
Selector类的常用方法:
public static Selector open() 打开一个选择器
public abstract int select() 选择一组键,通道已经为IO做好准备
public abstract Set<SelectionKey> selectedKeys() 返回此选择器已选择的key
在进行非阻塞网络开发时需要使用SelectableChannel类向Select类注册,而且在新IO中实现网络程序需要依靠ServerSocketChannel与SocketChannel类,这两个都是SelectableChannel的子类,SelectableChannel提供了注册Selector的方法和阻塞模式
ServerSocketChannel类的常用方法:
public abstract SelectableChannel configBlocking(boolean block) 调整此通道的阻塞模式,如果为true将被设置为阻塞模式,如果为false将被设置为非阻塞模式
public final SelectionKey register(Selector sel, int ops) 向指定的选择器注册通道并设置Selector域,返回一个选择键
public static ServerSocketChannel open() 打开服务器的套接字通道
public abstract ServerSocket socket() 返回与此通道关联的服务器套接字
在使用register()方法时需要指定一个选择器(Selector对象)以及Select域,Selector对象可以通过Selector中的open()方法取得,而Selector域则在SelectionKey类中定义
4种Selector域
public static final int OP_ACCEPT 相当于ServerSocket中的accept()操作
public static final int OP_CONNECT 连接操作
public static final int OP_READ 读操作
public static final int OP_WRITE 写操作
建立一个非阻塞的服务器端:
首先通过Selector.open()方法打开一个选择器,之后通过ServerSocketChannel类中的open()方法打开一个服务器套接字通道。最重要的是configureBlocking()方法,将服务器设置为非阻塞状态,之后通过ServerSocketChannel的socket()方法返回一个ServerSocket对象,并在8888端口绑定服务器的监听端口。程序的最后使用register()方法将选择器注册为accept方式,等待客户端连接。
如果要使用服务器想客户端发送信息,则需要通过SelectionKey类中提供的方法判断服务器的操作状态。而要想取得客户端的连接也需要使用SelectionKey类
- Java -- 新IO -- 目录
20.1 Java 新IO简介 20.2 缓冲区与Buffer 例:演示缓冲区的操作流程 Class : IntBufferDemo01 20.2.2 深入缓冲区操作 20.2.3 创建子缓冲区 20 ...
- Java——新IO 通道
import java.io.File; import java.io.FileOutputStream; import java.nio.ByteBuffer; import java.nio.ch ...
- 怎样获取java新IO的Path文件大小
import org.junit.Test; import java.io.IOException; import java.nio.file.Files; import java.nio.file. ...
- Java——新IO 缓冲区与Buffer
缓冲区和Buffer import java.nio.IntBuffer; //================================================= // File Na ...
- JAVA(六)数据库/网络编程/新IO
成鹏致远 | lcw.cnblog.com |2014-02-05 数据库 1.JDBC概述 JDBC(Java Database Connectivity,Java数据库连接)提供了一种与平台无关的 ...
- java 21 - 15 新IO流 NIO
1:JDK4 新IO要了解的类 Buffer(缓冲),Channer(通道) 2:JDK7 要了解的新IO类 Path:与平台无关的路径. Paths:包含了返回Path的静态方法. public ...
- Java 8特性尝鲜:新新IO
Java 8特性尝鲜:新新IO 在这个专题前面的文章中,我们已经看到,使用Java8的lambda表达式对现有的JDK1.2 I/O库的提升,主要是可以使用lambda表达式来构造java.io.Fi ...
- Java API —— IO流(数据操作流 & 内存操作流 & 打印流 & 标准输入输出流 & 随机访问流 & 合并流 & 序列化流 & Properties & NIO)
1.操作基本数据类型的流 1) 操作基本数据类型 · DataInputStream:数据输入流允许应用程序以与机器无关方式从底层输入流中读取基本 Java 数据类型.应用程序可以使用数据输出 ...
- Java基础--IO
1,流的认识和分类 2,Java种处理流的IO类架构 3,字节流和字符流转换 4,NIO的概述 5,Java IO关闭资源 1,流的认识和分类 流是一组有顺序的,有起点和终点的字节集合,是对数据传输的 ...
随机推荐
- (转)ubuntu 14.04下安装hadoop2.6(伪分布式)
安装: http://pingax.com/install-hadoop2-6-0-on-ubuntu/ 写的非常好(国外人比较实在,他说的单机实际上是伪分布式...). 另外要注意的是,如果对新 ...
- JavaWeb学习记录(一)——response响应头之缓存设置与下载功能的实现
一.HTTP中常用响应头 Location: http://www.it315.org/index.jsp Server:apache tomcat Content-Encoding: gzip Co ...
- LeetCode(228) Summary Ranges
Given a sorted integer array without duplicates, return the summary of its ranges. For example, give ...
- poj1128 拓扑序(DFS)
题意:给出一张图,它是由一系列字母框按一定顺序从下到上摆放,因此上面的字母框会覆盖一部分下面的字母框,确保每个字母框的四条边都至少会出现一个点,要求输出所有可行的摆放顺序,字典序从小到大输出. 首先可 ...
- knockoutJs基础1 - 简单的knockoutjs实现
简单的knockoutjs实现 1.knockoutJs是在MVVM的机制下实现的,所以要有view(HTML页面中的DOM标签)和viewModel(JavaScript中的js代码). 2.在vi ...
- 【LOI2005】【P1306】河流
树归题,本来比较简单,但是因为几个思想搞错了,所以卡了两天 原题: 几乎整个Byteland 王国都被森林和河流所覆盖.小点的河汇聚到一起,形成了稍大点的河.就这样,所有的河水都汇聚并流进了一条大河, ...
- 《剑指Offer》之替换空格
1.题目描述 请实现一个函数,将一个字符串中的空格替换成"%20".例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 2.代码实 ...
- E:nth-child(n)实现奇偶匹配
<style> li:nth-child(2n){color:#f00;} /* 偶数 */ li:nth-child(2n+1){color:#000;} /* 奇数 */ </s ...
- QueryRunner使用
在相继学习了JDBC和数据库操作之后,我们明显感到编写JDBC代码并非一件轻松的事儿.为了帮助我们更高效的学习工作,从JDBC的繁重代码中解脱出来,老佟给我们详尽介绍了一个简化JDBC操作的组件——D ...
- java_linear list
1.线性表的顺序存储结构,类似ArrayList package collectionsFramework.linearlist; import java.util.Arrays; /** * @Pa ...