现在使用NIO的场景越来越多,很多网上的技术框架或多或少的使用NIO技术,譬如Tomcat,Jetty。学习和掌握NIO技术已经不是一个JAVA攻城狮的加分技能,而是一个必备技能。再者,现在互联网的面试中上点level的都会涉及一下NIO或者AIO的问题(AIO下次再讲述,本篇主要讲述NIO),掌握好NIO也能帮助你获得一份较好的offer。 驱使博主写这篇文章的关键是网上关于NIO的文章并不是很多,而且案例较少,针对这个特性,本文主要通过实际案例主要讲述NIO的用法,每个案例都经过实际检验。博主通过自己的理解以及一些案例希望能给各位在学习NIO之时多一份参考。博主能力有限,文中有不足之处欢迎之处。

本文持续更新,转载请保留原文链接。

概述

NIO主要有三大核心部分:Channel(通道),Buffer(缓冲区), Selector。传统IO基于字节流和字符流进行操作,而NIO基于Channel和Buffer(缓冲区)进行操作,数据总是从通道读取到缓冲区中,或者从缓冲区写入到通道中。Selector(选择区)用于监听多个通道的事件(比如:连接打开,数据到达)。因此,单个线程可以监听多个数据通道。

NIO和传统IO(一下简称IO)之间第一个最大的区别是,IO是面向流的,NIO是面向缓冲区的。 Java IO面向流意味着每次从流中读一个或多个字节,直至读取所有字节,它们没有被缓存在任何地方。此外,它不能前后移动流中的数据。如果需要前后移动从流中读取的数据,需要先将它缓存到一个缓冲区。NIO的缓冲导向方法略有不同。数据读取到一个它稍后处理的缓冲区,需要时可在缓冲区中前后移动。这就增加了处理过程中的灵活性。但是,还需要检查是否该缓冲区中包含所有您需要处理的数据。而且,需确保当更多的数据读入缓冲区时,不要覆盖缓冲区里尚未处理的数据。

IO的各种流是阻塞的。这意味着,当一个线程调用read() 或 write()时,该线程被阻塞,直到有一些数据被读取,或数据完全写入。该线程在此期间不能再干任何事情了。 NIO的非阻塞模式,使一个线程从某通道发送请求读取数据,但是它仅能得到目前可用的数据,如果目前没有数据可用时,就什么都不会获取。而不是保持线程阻塞,所以直至数据变的可以读取之前,该线程可以继续做其他的事情。 非阻塞写也是如此。一个线程请求写入一些数据到某通道,但不需要等待它完全写入,这个线程同时可以去做别的事情。 线程通常将非阻塞IO的空闲时间用于在其它通道上执行IO操作,所以一个单独的线程现在可以管理多个输入和输出通道(channel)。

Channel

首先说一下Channel,国内大多翻译成“通道”。Channel和IO中的Stream(流)是差不多一个等级的。只不过Stream是单向的,譬如:InputStream, OutputStream.而Channel是双向的,既可以用来进行读操作,又可以用来进行写操作。

NIO中的Channel的主要实现有:

FileChannel

DatagramChannel

SocketChannel

ServerSocketChannel

这里看名字就可以猜出个所以然来:分别可以对应文件IO、UDP和TCP(Server和Client)。下面演示的案例基本上就是围绕这4个类型的Channel进行陈述的。

Buffer

NIO中的关键Buffer实现有:ByteBuffer, CharBuffer, DoubleBuffer, FloatBuffer, IntBuffer, LongBuffer, ShortBuffer,分别对应基本数据类型: byte, char, double, float, int, long, short。当然NIO中还有MappedByteBuffer, HeapByteBuffer, DirectByteBuffer等这里先不进行陈述。

Selector

Selector运行单线程处理多个Channel,如果你的应用打开了多个通道,但每个连接的流量都很低,使用Selector就会很方便。例如在一个聊天服务器中。要使用Selector, 得向Selector注册Channel,然后调用它的select()方法。这个方法会一直阻塞到某个注册的通道有事件就绪。一旦这个方法返回,线程就可以处理这些事件,事件的例子有如新的连接进来、数据接收等。

FileChannel

看完上面的陈述,对于第一次接触NIO的同学来说云里雾里,只说了一些概念,也没记住什么,更别说怎么用了。这里开始通过传统IO以及更改后的NIO来做对比,以更形象的突出NIO的用法,进而使你对NIO有一点点的了解。

传统IO vs NIO

首先,案例1是采用FileInputStream读取文件内容的:

public static void method2(){

InputStream in = null;

try{

in = new BufferedInputStream(new FileInputStream("src/nomal_io.txt"));

byte [] buf = new byte[1024];

int bytesRead = in.read(buf);

while(bytesRead != -1)

{

for(int i=0;i

System.out.print((char)buf[i]);

bytesRead = in.read(buf);

}

}catch (IOException e)

{

e.printStackTrace();

}finally{

try{

if(in != null){

in.close();

}

}catch (IOException e){

e.printStackTrace();

}

}

}

输出结果:(略)

案例是对应的NIO(这里通过RandomAccessFile进行操作,当然也可以通过FileInputStream.getChannel()进行操作):

public static void method1(){

RandomAccessFile aFile = null;

try{

aFile = new RandomAccessFile("src/nio.txt","rw");

FileChannel fileChannel = aFile.getChannel();

ByteBuffer buf = ByteBuffer.allocate(1024);

int bytesRead = fileChannel.read(buf);

System.out.println(bytesRead);

while(bytesRead != -1)

{

buf.flip();

while(buf.hasRemaining())

{

System.out.print((char)buf.get());

}

buf.compact();

bytesRead = fileChannel.read(buf);

}

}catch (IOException e){

e.printStackTrace();

}finally{

try{

if(aFile != null){

aFile.close();

}

}catch (IOException e){

e.printStackTrace();

}

}

}

输出结果:(略)

通过仔细对比案例1和案例2,应该能看出个大概,最起码能发现NIO的实现方式比叫复杂。有了一个大概的印象可以进入下一步了。

Buffer的使用

从案例2中可以总结出使用Buffer一般遵循下面几个步骤:

分配空间(ByteBuffer buf = ByteBuffer.allocate(1024); 还有一种allocateDirector后面再陈述)

写入数据到Buffer(int bytesRead = fileChannel.read(buf);)

调用filp()方法( buf.flip();)

从Buffer中读取数据(System.out.print((char)buf.get());)

调用clear()方法或者compact()方法

Buffer顾名思义:缓冲区,实际上是一个容器,一个连续数组。Channel提供从文件、网络读取数据的渠道,但是读写的数据都必须经过Buffer。如下图:

向Buffer中写数据:

从Channel写到Buffer (fileChannel.read(buf))

通过Buffer的put()方法 (buf.put(…))

从Buffer中读取数据:

从Buffer读取到Channel (channel.write(buf))

使用get()方法从Buffer中读取数据 (buf.get())

可以把Buffer简单地理解为一组基本数据类型的元素列表,它通过几个变量来保存这个数据的当前位置状态:capacity, position, limit, mark:

java nio技术_攻破JAVA NIO技术壁垒相关推荐

  1. java 核型技术_你必须掌握的 21 个 Java 核心技术!(转自Java技术栈)

    写这篇文章的目的是想总结一下自己这么多年来使用java的一些心得体会,希望可以给大家一些经验,能让大家更好学习和使用Java. 这次介绍的主要内容是和J2SE相关的部分,另外,会在以后再介绍些J2EE ...

  2. java 字节码增强原理_深入浅出Java探针技术1--基于java agent的字节码增强案例

    Java agent又叫做Java 探针,本文将从以下四个问题出发来深入浅出了解下Java agent 一.什么是java agent? Java agent是在JDK1.5引入的,是一种可以动态修改 ...

  3. java前沿技术_互联网百强企业架构师告诉你,Java应该这么学!云和数据超全面Java中级程序员学习路线图重磅发布!...

    作为常居编程语言排行榜第一名的编程语言,Java语言以其稳定性.健壮性著称,是一门非常成熟的编程语言,多年来一直是国际上众多企业的首选编程语言. Java语言不仅吸收了C++语言的各种优点,还摒弃了C ...

  4. java图片管理系统_基于Java Web技术的图片管理系统的设计与实现.doc

    基于Java Web技术的图片管理系统 的设计与实现 本科毕业设计 目 录 第1章 引言6 1.1 课题研究目的及意义6 1.2 课题研究的内容7 2.1 用户功能需求7 图片收藏数据库查询系统图片收 ...

  5. java探针 字节码增强_深入浅出Java探针技术1--基于java agent的字节码增强案例

    Java agent又叫做Java 探针,本文将从以下四个问题出发来深入浅出了解下Java agent 一.什么是java agent? Java agent是在JDK1.5引入的,是一种可以动态修改 ...

  6. JAVA物联所需技术_基于JAVA多线程技术解决物联云端服务雪崩效应的方法与流程...

    本发明涉及互联网技术领域,特别涉及一种基于JAVA多线程技术解决物联云端服务雪崩效应的方法. 背景技术: 目前,物联云系统已经作为普遍的智能电视平台出现在我们面前,而细致分析物联云系统我们可以发现,当 ...

  7. java验证码技术_验证码技术(JavaWeb 中验证码的实现 )

    二.实践 下面通过程序演示验证码产生和实现验证的过程. 1.验证码的产生 创建一个Servlet完成验证码的产生.首先通过随机数的产生类Random随机产生一个4位的验证码, 并将其存入session ...

  8. java教学目标_成为Java高手的25个学习目标

    1.需要精通面向对象分析与设计(OOA/OOD).涉及模式(GOF,J2EEDP)以及综合模式,应该了解UML,尤其是 class,object,interaction以及statediagrams. ...

  9. java基础知识点_「Java面试题/知识点精华集」20000+字的Java基础知识篇(2020最新版) !

    " 本文已经收录进我的 79K Star 的 Java 开源项目 JavaGuide:https://github.com/Snailclimb/JavaGuide (「Java学习+面试指 ...

最新文章

  1. 0607am抽象类接口析构方法tostring小知识点
  2. js/jquery判断浏览器的方法总结
  3. 挖一挖曹大 holmes 的设计与实现
  4. ei会议论文录用但不参加会议_会议论文投稿可以不参会吗
  5. 机房收费系统——转换list泛型时,字段名称不正确应出现故障
  6. 工作169:删除操作
  7. Fence Repair(不会优先队列的看过来)
  8. Play静态文件调用
  9. MATLAB说文本命令超过,MATLAB基础
  10. 求数组子序列和最大值
  11. java学习视频 java常用23种设计模式
  12. 数据可视化:经典图表大全
  13. 英文java简历模板下载_JAVA技术人员英文简历模板
  14. Jmeter 面试题
  15. java 切图 软件_Java 切图
  16. 用计算机计算勾股定理,勾股计算器(勾股定理计算器)
  17. macOS:隐私设置与数据库相关的问题
  18. 这篇文章有毒《持续更新中。。。》
  19. java手机号中间4位使用*替换
  20. 安卓app源码和设计报告——简易记账本

热门文章

  1. SAP Spartacus cxFocus Directive施加后导致tabindex为-1的副作用研究
  2. 外部系统调用PO的webservice服务,往SAP系统发送数据,用的XISOAPAdapter的方式,出现错误
  3. SAP Spartacus home 页面的 cx-page-slot selector
  4. SAP Spartacus CmsPage的加载逻辑
  5. 如何访问SAP Spartacus里的config数据
  6. 将SAP Analytics Cloud嵌入到SAP Cloud for Customer里去
  7. hybris backoffice创建product遇到的synchronization问题和解答
  8. Controller FioriTest.view.LineItem couldn't be instantiated
  9. 关于SAP Spartacus添加缺失的cost center route配置的必要性
  10. Customizing Download - product hierarchy