这么说吧,NIO很简单,其实就是个牛逼IO,吹牛逼用的

极简教程,五分钟快速入门之NIO,搭配后面实战以及NIO源码分析

0 ) 哈哈,其实我是个标题党,NIO不是牛逼IO,是非阻塞IO

NIO 也能算是一种思想,非阻塞IO通信思想,Netty就是基于NIO思想的NIO框架,

想花5分钟知道Netty是什么的可以看看这篇:这么说吧,Netty很简单,其实就是个Jar包,是作为通讯组件用的

什么是非阻塞?(为什么我没有说什么是IO,既然你都学到NIO了,,,要是不知道什么是IO的话…那就接下去看下面的内容吧)

1 )先上 异步非阻塞例子:

老张爱喝茶,废话不说,煮开水。

出场人物:老张,水壶两把(普通水壶,简称水壶;会响的水壶,简称响水壶)。

1 老张把水壶放到火上,原地不动等水开。(同步阻塞) ---------->老张觉得自己有点傻

2 老张把水壶放到火上,去客厅看毛骗,时不时去看看水开没有。(同步非阻塞) ------>老张觉得自己有点傻

于是变高端了,买了把会响笛的那种水壶。水开之后,能大声发出嘀~~~~的响声。

3 老张把响水壶放到火上,立等水开。(异步阻塞) ------>老张觉得自己有点傻

4 老张把响水壶放到火上,去客厅看毛骗,水壶响之前不再去看它,响了再去拿壶。(异步非阻塞) --->嗯,老张觉得自己棒棒哒

2 ) 小结:

简单讲,Java NIO的非阻塞模式就是,使一个线程从某通道发送请求读取(或者写入)数据,(如烧水)

他不是保持线程阻塞,所以在读取(或者写入)数据前,该线程可以继续做其他的事情。 (例如客厅看毛骗)

3 ) IO VS NIO 的比较 (不同之处)

1.IO只能实现阻塞式的网络通信。NIO能够实现非阻塞的网络通信.(废话)

2.标准IO基于字节/字符流进行操作;而NIO是基于通道(Channel)进行操作的。(话说,通往女人心灵的通道是xxx道…)

3.流的读写通常是单向的,要么输入,要么输出,不能既是输入流又是输出流。通道是双向的,既可以写数据到通道,又可以从通道中读取数据;

4 ) 学习目标 :

虽然现在我们不会直接编写NIO来完成我们的网络层通讯,而是使用成熟的基于NIO的网络框架来实现我们的网络层。如,netty、mina。但对NIO网络编程过程的了解,非常有助于我们更深入的理解netty、mina等网络框架,以至于能更好的使用它们。有人问了,不学这个对我敲代码有何影响,可以说,毛影响都没。那学来干嘛,爱干嘛干嘛。

5 ) NIO → 引出 java NIO:

知道什么是NIO后,我们再来看看java NIO的三个重要组成部分

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

当然,类比学习是比较好的学习方法,这里我仍然跟传统IO做比较,希望他不要打我

6 ) Channel ( 通道 ):

顾名思义,就是通向什么的道路,为某个提供了渠道。

1.传统IO中,Stream是单向的,比如InputStream只能进行读取操作,OutputStream只能进行写操作。

而Channel是双向的,既可用来进行读操作,又可用来进行写操作。

2.具体的常见实现通道有FileChannel,SocketChanel,ServerSocketChannel,DatagramChannel等

跟具体的实现流FileInputStream,FileOutputStream,FileReader,FileWriter,节点流包装流缓冲流等等功能类似

7 ) Buffer(缓冲区):

是NIO中非常重要的一个东西,实际上就是一个容器,是一个连续数组。在NIO中所有数据的读和写都离不开Buffer。在NIO中,读取的数据只能放在Buffer中。同样地,写入数据也是先写入到Buffer中。

上面的图描述了从一个客户端向服务端发送数据,然后服务端接收数据的过程。

简单的讲就是,要想使用Channel(通道)传递数据,必须先把数据丢进Buffer(缓冲区,容器)里。

在NIO中,Buffer是一个顶层父类,它是一个抽象类,常用的Buffer的子类有:

ByteBuffer,IntBuffer,CharBuffer,LongBuffer,DoubleBuffer,FloatBuffer,ShortBuffer等

8 ) Selector(选择器) :

可以说它是NIO中最关键的一个部分,Selector的作用就是用来轮询每个注册的Channel,一旦发现Channel有注册的事件发生,便获取事件然后进行处理。

这是在一个单线程中使用一个Selector处理3个Channel的图示:

以前传统socket编程时,accept方法会一直阻塞,直到有客户端请求的到来,并返回socket进行相应的处理。整个过程是就像上面的例子那样,直到水壶烧开了(响应回去了)才能去处理下一个请求.当然我们也可以用线程池的模式.

NIO则为我们提供了更好的解决方案,Selector选择器能够检测多个注册的通道上是否有事件发生,如果有事件发生,便获取事件然后针对每个事件进行相应的响应处理。这样一来,只是用一个单线程就可以管理多个通道,也就是管理多个连接。这样使得只有在连接真正有读写事件发生时,才会调用函数来进行读写,就大大地减少了系统开销,并且不必为每个连接都创建一个线程,不用去维护多个线程,并且避免了多线程之间的上下文切换导致的开销。并且是按顺序处理,基于通道(Channel)和缓冲区(Buffer)来传输和保存数据。

与Selector有关的一个关键类是SelectionKey,一个SelectionKey表示一个到达的事件,这2个类构成了服务端处理业务的关键逻辑。

好的,我不贴源码,大家能否理解?

原文发布于微信公众号 - java进阶架构师(java_jiagoushi)

原文发表时间:2018-08-30

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏向治洪

老司机带你玩转web service

当大型需求被数个公司分割开来,各公司系统相互交换数据的问题就会接踵而来。毕竟是多家不同的公司的产品,研发开发语言、采用技术框架基本上是百花齐放。怎样让自家系统提...

2899
来自专栏玄魂工作室

Hacker基础之Linux篇:系统简介特别番之Kali Linux

0x01. 前言 作为安全界的明星,Kali可以说是无人不知无人不晓,当然,除了Kali之外,我们还有许多的可以选择的工具,比如: ParrotSec ? ...

3926
来自专栏杨建荣的学习笔记

一个oracle bug的简单验证(r8笔记第45天)

最近碰到了一个oracle bug,但是我感觉还是有些运气的成分,虽然错误日志和bug描述吻合,版本也完全对应,现在有几个问题在我脑海中翻腾,就是这个问题是不是...

3637
来自专栏Python小屋

使用Python开发会聊天的智能小机器人

本文重点演示使用socket实现TCP通信以及字典和集合的用法,客户端发来信息之后,服务端会尽量猜测客户端要表达的真正意思,然后选择合适的内容进行回复。 服务...

37212
来自专栏腾讯Bugly的专栏

Android 开发必备知识:我和 Gradle 有个约会

0、讲个故事 0.1 Ant,我还真以为你是只蚂蚁 真正开始近距离接触编程其实是在2012年,年底的时候带我的大哥说,咱们这个 app 发布的时候手动构建耗时太...

3644
来自专栏IT可乐

Spring详解(一)------概述

  本系列教程我们将对 Spring 进行详解的介绍,相信你在看完后一定能够有所收获。 1、什么是 Spring ?   Spring是一个开源框架,Sprin...

2047
来自专栏JackieZheng

Spring实战——无需一行xml配置实现自动化注入

  已经想不起来上一次买技术相关的书是什么时候了,一直以来都习惯性的下载一份电子档看看。显然,如果不是基于强烈的需求或强大的动力鞭策下,大部分的书籍也都只是蜻蜓...

2176
来自专栏跟着阿笨一起玩NET

C#远程调用技术WebService葵花宝典

1092
来自专栏Gaussic

Spring In Action 4(Spring实战第四版)翻译与理解 第一章 付诸行动

        这几天笔者阅读了一下Spring In Action 4,感觉还是有一定的收获的。在之前的项目上,只会简单地使用Spring MVC,对于很多概...

4332
来自专栏情情说

《深入实践Spring Boot》阅读笔记之一:基础应用开发

上上篇「1718总结与计划」中提到,18年要对部分项目拆分,进行服务化,并对代码进行重构。公司技术委员会也推荐使用spring boot,之前在各个技术网站中也...

3569

扫码关注云+社区

领取腾讯云代金券