JAVA NIO

中文教程 http://ifeve.com/java-nio-all/
原地址 http://tutorials.jenkov.com/java-nio/index.html

概述

核心组件:

  • Channels
  • Buffers
  • Selectors

Channel 有点像流,数据可以从Channel读到Buffer中,也可以从Buffer写到Channel中,Channel的主要实现:

  • FileChannel
  • DatagramChannel
  • SocketChannel
  • ServerSocketChannel
    这些涵盖了UDP和TCP网络IO,和文件IO

Buffer 在NIO中的主要实现:

  • ByteBuffer
  • CharBuffer
  • DoubleBuffer
  • FloatBuffer
  • IntBuffer
  • LongBuffer
  • ShortBuffer
    覆盖了通过IO发送的基本数据类型:byte、short、int、long、float、double 和 characters

Selectors 允许单线程处理多个Channel,如果应用有很多连接(Channel),但是每个连接只有很低的流量,使用Selectors就会很方便,如下图一个聊天服务,一个线程使用一个Selector处理3个Channel
多线程的上下文切换开销很大,每个线程还得占用资源,使用Selector便可以使用少量的线程,处理更多的Channel

image.png

要使用Selector,需要向Selector中注册Channel,然后调用select()方法,这个方法会一直阻塞到某个注册的Channel有事件就绪。一旦这个方法返回,线程就就可以处理这些事件。事件的例子有如新连接进来,数据接收等。

详述

Channel
channel和流(stream)的区别:

  • 既可以从Channel中读数据,同时也可以往通道中写数据。流的读写是单向的
  • Channel可以异步的进行读写
  • Channel总是把数据读到Buffer或者从一个Buffer中写入

Buffer
缓冲区实际上就是一块可以先写入数据,然后从中读取数据的内存块,这块内存被包装成NIO Buffer对象,并提供一组方法便于访问。

使用Buffer去读或者写数据一般遵循以下四个步骤:

  1. 写入数据到Buffer
  2. 调用buffer.flip()
  3. 从Buffer中读出数据
  4. 调用buffer.clear()或者buffer.compact()

当向Buffer写入数据时,Buffer会跟踪写入的数据量,一旦需要读这些数据,需要使用filp()方法将Buffer从写模式切换到读模式,在读的模式下,便可以读取之前写入的所有数据。
一旦读取完所有数据,需要清空缓存区,让他可以再次被写入(调用clear()或者compact())。clear方法会清空整个缓冲区,compact只会清除已经读过的数据,未读的数据会移到缓冲区起始位置,新写入的数据会放到这些未读数据之后。

Buffer的三个属性:

  1. capacity :缓冲区内存块的容量
  2. position :根据读或写操作动态改变。写:初始为0,写入数据后,position移到下一个可插入数据的位置;读:将Buffer切换为read模式,position重置为0,读取数据时,position移动到下一个可读位置
  3. limit:写模式下,代表最多能写入多少数据,等同于capacity;读模式下,代表最多能读多少数据,即写模式下的position值。相当于你能读到之前写入的所有数据。
image.png

Java NIO 和 IO的区别

IO NIO
面向流 面向缓冲
阻塞IO 非阻塞IO
Selectors

面向流与面向缓冲
面向流意味着每次从流中读取一个或多个字节,直到读取完所有字节,没有被缓存在任何地方。
面向缓冲便是将数据读取到一个缓冲区,需要时可以在缓冲区中前后移动取数据,增加灵活性

阻塞与非阻塞IO
阻塞IO意味着一个线程调用read()或write()时,该线程阻塞,直到数据被读取或者完全写入,此过程期间该线程不能干别的事情。
非阻塞IO是一个线程通过一个Channel请求读取数据,仅能读取当前可用数据,如果没有可用数据,便不会读取,而不是保持线程阻塞。所以直至数据变成可读取之前,该线程可以继续做别的事情。一个线程管理多个Channel,便可以在空闲时间处理其他Channel上的任务

Selectors 帮助一个Thread管理多个Channel

比如读取如下文本

Name: Anna
Age: 25
Email: anna@mailserver.com
Phone: 1234567890

IO的方法:

InputStream input = ... ; // get the InputStream from the client socket

BufferedReader reader = new BufferedReader(new InputStreamReader(input));

String nameLine   = reader.readLine();
String ageLine    = reader.readLine();
String emailLine  = reader.readLine();
String phoneLine  = reader.readLine();

每次使用reader.readLine()得到返回值时,便知道该行已经读取完毕

使用NIO

ByteBuffer buffer = ByteBuffer.allocate(48);

int bytesRead = inChannel.read(buffer);

while(! bufferFull(bytesRead) ) {
    bytesRead = inChannel.read(buffer);
}

每次isChannel.read()返回时,缓存区内存在哪些数据并不清楚,需要bufferFull()判断缓冲区是否准备好被处理。

所以使用NIO对于读取数据解析过程会比阻塞IO读取数据更复杂

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,029评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,395评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,570评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,535评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,650评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,850评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,006评论 3 408
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,747评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,207评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,536评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,683评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,342评论 4 330
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,964评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,772评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,004评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,401评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,566评论 2 349

推荐阅读更多精彩内容