前面一篇中已经介绍了基本IO的使用以及最简单的阻塞服务器的例子,本篇就来介绍下NIO的相关内容,前面的分享可以参考目录:

  1. 网络IO的基本知识与概念
  2. 普通IO以及BIO服务器
  3. NIO的使用与服务器Hello world
  4. Netty的使用与服务器Hello world

NIO,也叫做new-IO或者non-blocking-IO,就暂且理解为非阻塞IO吧。

为什么选择NIO

那么NIO相对于IO来说,有什么优势呢?总结来说:

  1. IO是面向流的,数据只能从一端读取到另一端,不能随意读写。NIO则是面向缓冲区的,进行数据的操作更方便了
  2. IO是阻塞的,既浪费服务器的性能,也增加了服务器的风险;而NIO是非阻塞的。
  3. NIO引入了IO多路复用器,效率上更高效了。

NIO都有什么

那么NIO都提供了什么呢?

  1. 基于缓冲区的双向管道,Channel和Buffer
  2. IO多路复用器Selector
  3. 更为易用的API

Buffer的使用

在NIO中提供了各种不同的Buffer,最常用的就是ByteBuffer:

可以看到,他们都有几个比较重要的变量:

  • capacity——容量,这个值是一开始申请就确定好的。类似c语言申请数组的大小。
  • limit——剩余,在写模式下初始的时候等于capacity;在读模式下,等于最后一次写入的位置
  • mark——标记位,标记一下position的位置,可以调用reset()方法回到这个位置。
  • posistion——位置,写模式下表示开始写入的位置;读模式下表示开始读的位置

总结来说,NIO的Buffer有两种模式,读模式和写模式。刚上来就是写模式,使用flip()可以切换到读模式。

关于这几个位置的使用,可以参考下面的代码:

public class ByteBufferTest {public static void main(String[] args) {ByteBuffer buffer = ByteBuffer.allocate(88);System.out.println(buffer);String value = "Netty权威指南";buffer.put(value.getBytes());System.out.println(buffer);buffer.flip();System.out.println(buffer);byte[] v = new byte[buffer.remaining()];buffer.get(v);System.out.println(buffer);System.out.println(new String(v));}
}

得到的输出为:

java.nio.HeapByteBuffer[pos=0 lim=88 cap=88]
java.nio.HeapByteBuffer[pos=17 lim=88 cap=88]
java.nio.HeapByteBuffer[pos=0 lim=17 cap=88]
java.nio.HeapByteBuffer[pos=17 lim=17 cap=88]
Netty权威指南

读者可以自己领会一下,这几个变量的含义。另外说明一点,如果遇到自己定义POJO类,就可以像这里的Buffer重载toString()方法,这样输出的时候就很方便了。

最后关于ByteBuffer在Channel中的使用,可以参考下面的代码:

public class BufferTest {public static void main(String[] args) throws IOException {String file = "xxxx/test.txt";RandomAccessFile accessFile = new RandomAccessFile(file,"rw");FileChannel fileChannel = accessFile.getChannel();// 20个字节ByteBuffer buffer = ByteBuffer.allocate(20);int bytesRead = fileChannel.read(buffer);// buffer.put()也能写入bufferwhile(bytesRead!=-1){// 写切换到读buffer.flip();while(buffer.hasRemaining()){System.out.println((char)buffer.get());}// buffer.rewind()重新读// buffer.mark()标记position buffer.reset()恢复// 清除缓冲区buffer.clear();// buffer.compact(); 清楚读过的数据bytesRead = fileChannel.read(buffer);}}
}

这样,就熟悉了Channel和ByteBuffer的使用。接下来,看看服务器中的应用吧。

NIO服务器例子

前面BIO的服务器,是来一个连接就创建一个新的线程响应。这里基于NIO的多路复用,可以这样写:


import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;
import java.util.Set;public class PlainNioServer {public void serve(int port) throws IOException {// 创建channel,并绑定监听端口ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.configureBlocking(false);ServerSocket ssocket = serverSocketChannel.socket();InetSocketAddress address = new InetSocketAddress(port);ssocket.bind(address);//创建selector,并将channel注册到selectorSelector selector = Selector.open();serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);final ByteBuffer msg = ByteBuffer.wrap("Hi\r\b".getBytes());for(;;){try{selector.select();}catch (IOException e){e.printStackTrace();break;}Set<SelectionKey> readyKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = readyKeys.iterator();while(iterator.hasNext()){SelectionKey key = iterator.next();iterator.remove();try{if(key.isAcceptable()){ServerSocketChannel server = (ServerSocketChannel)key.channel();SocketChannel client=  server.accept();client.configureBlocking(false);client.register(selector, SelectionKey.OP_WRITE | SelectionKey.OP_READ, msg.duplicate());System.out.println("accepted connection from "+client);}if(key.isWritable()){SocketChannel client = (SocketChannel) key.channel();ByteBuffer buffer = (ByteBuffer) key.attachment();while(buffer.hasRemaining()){if(client.write(buffer)==0){break;}}client.close();}}catch (IOException e){key.cancel();try{key.channel().close();} catch (IOException ex){ex.printStackTrace();}}}}}public static void main(String[] args) throws IOException {PlainNioServer server = new PlainNioServer();server.serve(5555);}
}

这里抽象来说是下面的步骤:

  1. 创建ServerSocketChannel并绑定端口
  2. 创建Selector多路复用器,并注册Channel
  3. 循环监听是否有感兴趣的事件发生selector.select();
  4. 获得事件的句柄,并进行处理

其中Selector可以一次监听多个IO处理,效率就提高很多了。

转载于:https://www.cnblogs.com/xing901022/p/8672418.html

漫谈Java IO之 NIO那些事儿相关推荐

  1. NIO详解(十三):Java IO 和NIO 总结

    1. 概述 下面总结了Java NIO和IO之间的主要差别 IO NIO 面向流 面向缓冲 阻塞IO 非阻塞IO 无 选择器 2. Java IO和 NIO的主要区别 2.1 面向流和面向缓冲区 Ja ...

  2. java输入输出流_金九银十准备季:Java异常+Java IO与NIO面试题(含答案)

    写在前面:2020年面试必备的Java后端进阶面试题总结了一份复习指南在Github上,内容详细,图文并茂,有需要学习的朋友可以Star一下! GitHub地址:abel-max/Java-Study ...

  3. Java IO BIO NIO

    Java IO BIO NIO 一.Java I/O概述 1.1 什么是流 1.2 流的分类 1.3 字符流 1.3.1 Reader 1.3.2 Writer 1.4 字节流 1.4.1 Input ...

  4. JAVA IO : BIO NIO AIO

    JAVA IO : BIO NIO AIO 同步异步.阻塞非阻塞概念 同步与异步 阻塞与非阻塞 IO VS NIO VS AIO 面向流与面向缓冲 阻塞与非阻塞IO BIO.NIO.AIO的JAVA实 ...

  5. 漫谈Java IO之 Netty与NIO服务器

    前面介绍了基本的网络模型以及IO与NIO,那么有了NIO来开发非阻塞服务器,大家就满足了吗?有了技术支持,就回去追求效率,因此就产生了很多NIO的框架对NIO进行封装--这就是大名鼎鼎的Netty. ...

  6. 五.Java IO、NIO、文件、通讯

    2019独角兽企业重金招聘Python工程师标准>>> Java 的 I/O 大概可以分成四组: 基于字节操作的 I/O :InputStream 和 OutputStream 基于 ...

  7. 【学习笔记】JAVA IO与NIO(new IO)的对比与不同IO模型的理解

    JAVA IO 分类: 几种IO 模型 1. 阻塞 IO 模型 2. 非阻塞 IO 模型 JAVA NIO 多路复用 IO 模型(即Java中的NIO) JAVA IO 思维导图: 分类: 按照流的方 ...

  8. Java IO(BIO, NIO, AIO) 总结

    文章转载自:JavaGuide 目录 BIO,NIO,AIO 总结 同步与异步 阻塞和非阻塞 1. BIO (Blocking I/O) 1.1 传统 BIO 1.2 伪异步 IO 1.3 代码示例 ...

  9. java io bio nio aio 详解

    BIO.NIO.AIO的区别: BIO就是基于Thread per Request的传统server/client实现模式, NIO通常采用Reactor模式, AIO通常采用Proactor模式, ...

  10. java IO、NIO、AIO详解

    概述 在我们学习Java的IO流之前,我们都要了解几个关键词 同步与异步(synchronous/asynchronous):同步是一种可靠的有序运行机制,当我们进行同步操作时,后续的任务是等待当前调 ...

最新文章

  1. php读取excel中数据库,ThinkPHP 框架实现的读取excel导入数据库操作示例
  2. 计算机专业带给我们的启示,一次电脑网络调查带给我的启示
  3. Magento布局layout.xml文件详解
  4. jQuery 插件开发指南
  5. 用方框图语言表示指令周期及其流程
  6. MySQL读写分离介绍及搭建
  7. java基础知识总结(经典)_Java基础知识总结(超级经典)(三)
  8. java 毕向东_毕向东java视频目录
  9. Leetcode|DFS|130. 被围绕的区域
  10. android qq 邮箱格式,QQ邮箱格式怎么写
  11. matlab中断概率仿真,使用Matlab进行误比特率仿真
  12. 出售时间的网站(跟王利芬创建的优米网其中一种模式一样)
  13. 小程序behavior
  14. 输入半径,求球的表面积和体积
  15. 关于微信异常烦人自动生成的聊天记录截图视频
  16. LoRa学习<二>:Rx Duty Cycle模式实验
  17. DOS下常用命令介绍
  18. 2019-08-01软件工程总结
  19. MySQL查询,关于日期和时间戳,查询时间的记录
  20. Android基础面试题

热门文章

  1. smale学习之数学表达式(day5)
  2. libSM.so.6: cannot open shared object file: No such file or directoryapt-file search libSM.so.6
  3. PyQt5简单的例子
  4. Python进行特征提取
  5. Caffe学习:使用pycaffe绘制网络结构
  6. 图像语义分析--深度学习方法
  7. python基于scipy拟合构建所需统计分析模型,可视化分析展示
  8. Python使用hashlib模块生成给定文本数据的签名摘要信息(包括各种哈希函数)
  9. 修改linux文件权限命令:chmod超级详细讲解
  10. Django实战(一)——教育网站