资讯专栏INFORMATION COLUMN

NIO学习笔记

JerryZou / 392人阅读

摘要:选择器核心类,能够检测多个注册的通道上是否有事件发生,因此一个线程可以管理多个通道。标记,记录当前的位置,可以通过恢复到的位置。而返回值记录了包括,,集合和集合等。学习参考系列教程入门

一、NIO的核心部分

通道(channel):用于读操作和写操作,主要负责数据的“运输”。相当于传统IO中的stream,不过stream是单向的。

缓冲区(buffer):一个容器,用于存储数据。

选择器(selector):核心类,能够检测多个注册的通道上是否有事件发生,因此一个线程可以管理多个通道。

二、为什么使用NIO

使用NIO主要就是为了提高IO的速度

传统IO是基于字节流字符进行操作的,而NIO是基于通道(channel)缓冲区(buffer)进行操作的,这样一来数据的偏移操作非常方便。

传统IO是阻塞的,如果发出IO请求后数据没有就绪,会处于阻塞状态,而NIO通过通道操作数据,因此一个通道无数据可读,可以切换到另一个通道。

NIO有选择器,因此单线程可以操作多个通道。

三、简单的NIO读和写例子

从文件中读取
与传统IO不同的是,使用NIO从文件中读取主要分为三步:
(1)从FileInputStream中获取channel;

FileInputStream fin = new FileInputStream( "readandshow.txt" );
FileChannel fc = fin.getChannel();

(2)创建buffer;

ByteBuffer buffer = ByteBuffer.allocate( 1024 );

(3)将数据从channel读到buffer中。

fc.read( buffer );

写入文件
类似的,利用NIO写入文件也分为三步:
(1)从FileInputStream中获取channel;

   FileOutputStream fout = new FileOutputStream( "writesomebytes.txt" );
   FileChannel fc = fout.getChannel();
   

(2)创建一个缓冲区并在其中放入一些数据;

   ByteBuffer buffer = ByteBuffer.allocate( 1024 );
   for (int i=0; i

(3)将数据从buffer写到通道中。

   fc.write( buffer );
   

四、buffer内部细节

flip()函数源码

public final Buffer flip() {
    limit = position;
    position = 0;
    mark = -1;
    return this;
}
 

这里可以注意到limit,position和mark三个变量
(1) capacity:表明可以储存在缓冲区中的最大数据容量。
(2) position:下一个可插入的位置(写buffer时)或者下一个可读的位置(读buffer时)。
(3) limit:最多能写多少数据(写buffer时,相当于capacity),可以读多少数据(在从通道读入缓冲区时)。
(4) mark:标记,记录当前position的位置,可以通过reset()恢复到mark的位置。

五、选择器

selector的创建

Selector selector = Selector.open();

因为选择器是用于管理通道的,因此需要将通道注册到相应的选择器上
channel.configureBlocking(false); //使用selector必须保证channel是非阻塞的模式
SelectionKey key = channel.register(selector, Selectionkey.OP_READ);

注意register的第二个参数表示对选择器对什么事件感兴趣。
返回值记录了包括channel,buffer,interest集合和ready集合等。

通过selector选择通道
可以使用select()函数进行选择,select()方法返回的int值表示有多少通道已经就绪。

selectedKeys()函数
一旦调用了select()方法,并且返回值表明有一个或更多个通道就绪了,然后可以通过调用selector的selectedKeys()方法,访问“已选择键集(selected key set)”中的就绪通道。这里的selectorKey的就是之前注册到该selector的通道。

示例程序

Selector selector = Selector.open();   //开启选择器
channel.configureBlocking(false);      //非阻塞模式
SelectionKey key = channel.register(selector, SelectionKey.OP_READ);//注册
while(true) {
  int readyChannels = selector.select();   //选择通道
  if(readyChannels == 0) continue;
  Set selectedKeys = selector.selectedKeys();   //获取通道
  Iterator keyIterator = selectedKeys.iterator();
  while(keyIterator.hasNext()) {
    SelectionKey key = keyIterator.next();
    if(key.isAcceptable()) {
        // a connection was accepted by a ServerSocketChannel.
    } else if (key.isConnectable()) {
        // a connection was established with a remote server.
    } else if (key.isReadable()) {
        // a channel is ready for reading
    } else if (key.isWritable()) {
        // a channel is ready for writing
    }
    keyIterator.remove();   //需要自己移除处理完的通道
  }
}

六、NIO和IO的使用场景

NIO具备一定的优点,但并不是说传统IO就一无是处

(1)在处理数据上,如果遇到逐行处理的情况,如:

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

传统的IO可以这样写:

BufferedReader reader = new BufferedReader(new InputStreamReader(input));
String nameLine   = reader.readLine();
String ageLine    = reader.readLine();
String emailLine  = reader.readLine();
String phoneLine  = reader.readLine();

但如果使用NIO:

    ByteBuffer buffer = ByteBuffer.allocate(48);
    int bytesRead = inChannel.read(buffer);

你就不知道缓冲区内是否刚好是一行数据,这样处理起来会比较麻烦。

(2)如果需要管理同时打开的成千上万个连接,这些连接每次只是发送少量的数据,例如聊天服务器,实现NIO的服务器可能是一个优势。
如果你需要维持许多打开的连接到其他计算机上,如P2P网络中,使用一个多带带的线程来管理你所有出站连接,可能是一个优势。
但如果你有少量的连接使用非常高的带宽,一次发送大量的数据,也许典型的IO服务器实现可能非常契合。

学习参考:http://ifeve.com/java-nio-all/ Java NIO 系列教程
https://www.ibm.com/developer... NIO入门

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/74999.html

相关文章

  • Netty学习笔记(一)

    摘要:是一个高性能事件驱动的异步的非堵塞的框架,用于建立等底层的连接,基于可以建立高性能的服务器。在中提供了两套,一套是针对标准输入输出,另一套就是网络编程。和是标准中的核心对象是对原中流的模拟,任何来源和目的数据都必须通过一个对象。 Netty是一个高性能 事件驱动的异步的非堵塞的IO(NIO)框架,用于建立TCP等底层的连接,基于Netty可以建立高性能的Http服务器。1、首先来复习下...

    lncwwn 评论0 收藏0
  • 好记性不如烂笔头——NIO学习笔记

    摘要:该线程在此期间不能再干任何事情了。线程通讯线程之间通过等方式通讯。选择器传统的模式会基于服务器会为每个客户端请求建立一个线程由该线程单独负贵处理一个客户请求。 本文是对NIO知识的归纳与整理 1.阻塞与同步 1)阻塞(Block)和非租塞(NonBlock): 阻塞和非阻塞是进程在访问数据的时候,数据是否准备就绪的一种处理方式,当数据没有准备的时候阻塞:往往需要等待缞冲区中的数据准备好...

    王伟廷 评论0 收藏0
  • 高并发

    摘要:表示的是两个,当其中任意一个计算完并发编程之是线程安全并且高效的,在并发编程中经常可见它的使用,在开始分析它的高并发实现机制前,先讲讲废话,看看它是如何被引入的。电商秒杀和抢购,是两个比较典型的互联网高并发场景。 干货:深度剖析分布式搜索引擎设计 分布式,高可用,和机器学习一样,最近几年被提及得最多的名词,听名字多牛逼,来,我们一步一步来击破前两个名词,今天我们首先来说说分布式。 探究...

    supernavy 评论0 收藏0
  • 高并发

    摘要:表示的是两个,当其中任意一个计算完并发编程之是线程安全并且高效的,在并发编程中经常可见它的使用,在开始分析它的高并发实现机制前,先讲讲废话,看看它是如何被引入的。电商秒杀和抢购,是两个比较典型的互联网高并发场景。 干货:深度剖析分布式搜索引擎设计 分布式,高可用,和机器学习一样,最近几年被提及得最多的名词,听名字多牛逼,来,我们一步一步来击破前两个名词,今天我们首先来说说分布式。 探究...

    ddongjian0000 评论0 收藏0
  • 高并发

    摘要:表示的是两个,当其中任意一个计算完并发编程之是线程安全并且高效的,在并发编程中经常可见它的使用,在开始分析它的高并发实现机制前,先讲讲废话,看看它是如何被引入的。电商秒杀和抢购,是两个比较典型的互联网高并发场景。 干货:深度剖析分布式搜索引擎设计 分布式,高可用,和机器学习一样,最近几年被提及得最多的名词,听名字多牛逼,来,我们一步一步来击破前两个名词,今天我们首先来说说分布式。 探究...

    wangdai 评论0 收藏0

发表评论

0条评论

JerryZou

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<