Skip to content

Java基础—NIO基础概念 #6

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
geekyouth opened this issue Sep 8, 2018 · 0 comments
Closed

Java基础—NIO基础概念 #6

geekyouth opened this issue Sep 8, 2018 · 0 comments
Labels

Comments

@geekyouth
Copy link
Owner

一、I/O & NIO

Java的IO流,根据类型不同划分为(具体继承这些IO类的子类非常多)

  • 基于字节操作的 I/O 接口:InputStreamOutputStream
  • 基于字符操作的 I/O 接口:WriterReader
  • 基于磁盘操作的 I/O 接口:File
  • 基于网络操作的 I/O 接口:Socket

Java传统的IO类操作都是阻塞的,在高并发的场景下性能令人堪忧。

Java NIO(Non-blocking IO)是JDK1.4之后推出的一套新IO接口——非阻塞IO,与传统IO接口的主要区别在于:

I/O NIO
线程阻塞 线程非阻塞
用流(Stream)的方式处理数据 用缓冲区(Buffer)的方式处理数据

二、NIO基本概念

  • Channel(通道)
  • Buffer(缓冲区)
  • Selector(选择器)

2.1 Channel

1). Channel,相对于Stream,有几点区别:

Channel Stream
双向(可以读写) 单向(只能读或只能写)
非阻塞操作 阻塞操作
基于Buffer 基于流

2). NIO数据的流向总是:

Channel ----> Buffer
Channel <---- Buffer

3). Channel主要有下面几种类型:

类型 说明
FileChannel 文件的数据读写
DatagramChannel UDP的数据读写
SocketChannel TCP的数据读写
ServerSocketChannel 监听TCP链接请求,并且创建SocketChannel

4). 具体获取Channel的类

类型 说明
FileChannel FileInputStream.getChannel() FileOutputStream.getChannel() RandomAccessFile.getChannel()
DatagramChannel DatagramChannel.open()
SocketChannel SocketChannel.open()
ServerSocketChannel ServerSocketChannel.open()

2.2 Buffer

Buffer实际上就是一块内存区,用于和Channel交互,需要注意的是:

Buffer是非线程安全的,如果需要在多线程环境中使用,则需要有同步锁。

1). Buffer基本概念

要真正理解Buffer,有一张图比较经典:

  • capacity: buffer的容量大小,一般在创建之后就不会再改变;
  • limit: buffer内存区中还未被读写的第一个element位置索引;
  • position: 下一个等待要被读写的element位置索引;
  • mark: 当调用reset方法时,position会被重置的位置索引;

通常,0 <= mark <= position <= limit <= capacity

buffers-modes

2). Buffer类型

Buffer名字 对应基础类型
ByteBuffer byte
CharBuffer char
DoubleBuffer double
FloatBuffer float
IntBuffer int
LongBuffer long

3). Buffer常用操作

buffer操作 具体
clear() limit=capacity, position=0, mark忽略
flip() limit= position, position=0, mark忽略
rewind() position=0, mark忽略
compact() (ByteBuffer才有) 将整块Buffer(从position~limit)移动到Buffer开始的位置(0~limit-position)

Buffer常用操作模式:

  • 把数据写入buffer;
  • 调用flip;
  • 从buffer中读取数据;
  • 调用buffer.clear()清空整个buffer 或者 buffer.compact()清空已经读取的buffer

2.3 Selector

Selector是NIO中的组件,检查一个或多个channel,实现一个线程管理多个网络链接。

overview-selectors

使用步骤:

  • 创建 selector
  • 注册channel到selector

Channel必须是非阻塞的。所以FileChannel不适用Selector,因为FileChannel不能切换为非阻塞模式。Socket channel可以正常使用。

参考链接

johnnian/Blog#36

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

1 participant