java NIO
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java NIO相关的知识,希望对你有一定的参考价值。
一、简介
1、I/O
I/O指的是计算机与外部世界,或者程序与计算机其他部分的接口,即输入/输出。
在JAVA中,通常都以流的方式完成I/O,通过一个Stream对象操作。这种操作方法是堵塞的,无法移动读取位置的(只能一直往下读,不能后退),并且效率较低。JAVA为了提高I/O效率,在1.4之后,推出了NIO。
2、NIO vs I/O
I/O | NIO |
面向流,一次读取一个或多个字节,在流中无法前后移动 | 面向缓存,读取的数据先统一放在缓存中,在缓存中能前后移动 |
堵塞,从流读取数据时,线程无法做其他事情 | 非堵塞,数据还未完整读取到缓存中时,线程可以先做其他事 |
一对一:一条线程负责一个数据操作任务 | 一对多,一条线程负责多个数据操作任务 |
二、主要概念
NIO要实现面向缓存的非堵塞数据读取,依赖"Channel(通道)"和"Buffer(缓冲区)";
NIO要实现一条线程管理多个数据操作,依赖"Selector(选择器)"。
1、Channel通道
定义
A channel represents an open connection to an entity such as a hardware device, a file, a network socket, or a program component that is capable of performing one or more distinct I/O operations, for example reading or writing.
即通过Channel,你可以和外部进行数据的读写。
虽然NIO的Channel和I/O的stream很像,不过还是有区别的:
- Channel总是面向缓存的,而流既可以一次读取一个或多个字节,也可以选择先把数据读到缓存中。
- Channel可读也可写,流只能读或者写。
- Channel可以异步读写
类型
根据Channel数据来源不同,Channel有不同的实现:
- FileChannel : A channel for reading, writing, mapping, and manipulating a file -> 用于文件的读写
- DatagramChannel : A selectable channel for datagram-oriented sockets -> 用于UDP的数据读写
- SocketChannel : A selectable channel for stream-oriented connecting sockets -> 用于TCP的数据读写
- ServerSocketChannel : A selectable channel for stream-oriented listening sockets -> 用于监听TCP连接请求,为每个请求再建立一个SocketChannel
I/O 和 NIO 数据操作对比
// I/O流操作 FileInputStream inputStream = new FileInputStream("io.txt"); byte[] data = new byte[1024]; while(inputStream.read(data) != -1){ // 从流中读取多个字节,进行操作 }
// NIO channel操作 // 从文件流中获取channel FileInputStream inputStream = new FileInputStream("nio.txt"); FileChannel fileChannel = inputStream.getChannel(); // 新建缓存,用于存放Channel读取的数据 ByteBuffer buffer = ByteBuffer.allocate(1024); // 通过Channel读取数据到缓存中 fileChannel.read(buffer);
Channel间数据传输
对于FileChannel之间,利用transferFrom和transferTo可以直接进行数据传输,提高性能。
将fromChannel中数据传输到toChannel 中,position指toChannel中开始的位置,count指接收的数据:
toChannel.transferFrom(fromChannel, position, count) 或
fromChannel.transferTo(position, count, toChannel)
2、buffer缓冲区
定义
A container for data of a specific primitive type.
A buffer is a linear, finite sequence of elements of a specific primitive type. Aside from its content, the essential properties of a buffer are its capacity, limit, and position.
buffer缓冲区是一块内存,用于存放原始类型数据。它的特点是:线性,有限,有序,只能存一种原始类型数据。
属性
- capacity : A buffer‘s capacity is the number of elements it contains. -> 缓冲区大小
- limit : A buffer‘s limit is the index of the first element that should not be read or written. -> 用于标记读写的边界。读模式,limit表示目前缓冲区内存放的数据量。写模式,limit表示缓冲区最大的存放数,等于capacity.
- position: A buffer‘s position is the index of the next element to be read or written. -> 标记目前读或写的位置
类型
根据buffer中存放的原始类型不同,有以下几种Buffer实现
- DoubleBuffer
- FloatBuffer
- IntBuffer
- LongBuffer
- ShortBuffer
- ByteBuffer
- CharBuffer
基本用法
- 调用allocate()分配大小
- channel写数据到buffer
- 调用flip() -> buffer默认是写模式,当要从Buffer中读数据时,需要手动调flip方法,转为读模式。(这时,limit置为position,position置为0)
- 从buffer中读数据
- 当要重新往buffer中写数据时,需要调用clear()或compact方法。
其他方法介绍
- clear : 将position置为0, limit置为capacity,清空buffer。对于还未读取的数据,直接丢失。
- compact:先将未读的数据复制到缓存的开头,position置到未读数据的后一位,limit置为capacity。
- rewind: 将position重置为0,这样我们可以重读Buffer数据
- mark和reset:用mark标记此时的posiiton,之后移动position。调用reset,会将position重置为mark标记的地方。
3、
以上是关于java NIO的主要内容,如果未能解决你的问题,请参考以下文章