第一次听人用男女关系讲 N(Non-Blocking)I(进)O(出),涨姿势了

2023-12-15 06:18

本文主要是介绍第一次听人用男女关系讲 N(Non-Blocking)I(进)O(出),涨姿势了,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

点击上方 好好学java ,选择 星标 公众号重磅资讯,干货,第一时间送达
今日推荐:推荐19个github超牛逼项目!个人原创100W +访问量博客:点击前往,查看更多

BIO:80 年代屌丝追妹

80 年代屌丝男买了一个 BP 机用来追妹,男士使用传呼台给女生留言:

男:下午一起看个电影?[早晨 10 点]

这是男生唯一心动的女生,所以一直守着自己的 BP 机,等待女生回复,就这样一天过去了,直到:

男:BP 没电,自动关机。

名词解释

  1. BP 机和传呼台指的是 BIO 中的流单向传输的特性,屌丝男士通过传呼台给 BP 机发送消息是单向的,如果是女生通过传呼台回复屌丝男士,也是单向的。

  2. 这个女生是男士唯一心动的女生,所以他傻等着 BP 机回复,即便可能一直不会有消息,这就是同步阻塞 IO,中 B 的概念。

BIO 的缺点

  1. 同步阻塞 IO,如果存在多个请求的时候,服务端必须通过多线程处理,增加了服务端的压力和创建销毁线程的开销。

  2. 如果连接一直没有响应,服务端也需要一直监听端口等待,浪费了服务端资源。

NIO:80 年代公子哥把妹

80 年代的公子哥买了一个大哥大,关键是这个公子哥太花心,同时中意了两个妹子,于是他就开始了把妹过程。
公子哥用大哥大给女 A 打电话:

公子哥 -> 女 A:下午一起看个电影?[早晨 10 点]
女 A -> 公子哥:我正在吃饭,你晚点再打过来?

公子哥用大哥大给女 B 打电话:

公子哥 -> 女 B:下午一起看个电影?[早晨 10 点 1 分]
女 B -> 公子哥:我正在吃饭,你晚点再打过来?

过了 10 分钟公子哥再次打电话询问

公子哥 -> 女 A:怎么样,有空吗?[早晨 10 点 10 分]
女 A -> 公子哥:我下午陪爸爸打马球,不去了。
公子哥 -> 女 B:怎么样,有空吗?[早晨 10 点 11 分]
女 B -> 公子哥:好呀,下午 3 点来我家接我吧。
公子哥 -> 女 B:好嘞,我开车去接你。

最终公子哥成功了追求到了女 B,这个故事告诉我们,成功的前提是有钱。(你怎么看?)

名词解释

  1. 公子哥用上了大哥大,可以实现双向的通话,这就是 NIO 中的 Channel,可以实现双向的数据流传输。

  2. 公子哥不用像 BP 机小哥一样死等着回复,每次打电话都能得到回复,挂断电话一会儿再来询问即可,这就是 Channel 的非阻塞特性,也就是 “N” 的体现。

  3. 公子哥可以同时撩两个妹子,这就是 NIO 的 IO 多路复用,也就是 Selector。

  4. 公子哥只能同时和一个人通话,这就是同步,所以 NIO 的全称叫做同步非阻塞 IO。

优缺点

  1. 非阻塞 IO 模型,不需要阻塞在特定的请求。

  2. 一个线程可以处理多个请求,不需要客户端和服务器端一比一的对应,没有多线程创建和销毁带来的系统开销。

  3. 服务端不需要死等请求,减少了服务端压力。

关键名词

  1. Channel,双向传输,非阻塞的通道,有FileChannel,DatagramChannel,ServerSocketChannel/SocketChannel 等。

  2. Buffer,数据块的读写,可以理解字节数组,效率高。四个重要属性:capacity 容量,position 位置, limit 上限,用户切换读写时候的游标,mark 标记,标记 position 的位置,分为堆内内存和堆外内存,也是 NIO 性能的关键内容。

  3. Selector,IO 多路复用的关键,实现了循环查看可以使用的 Channel,解决死等问题。

  4. Selector 实现有多种方式,自己写一个数组循环也是方式,也可以实现 IO 多路复用,只是性能好坏而已,所以基于底层 poll、select和epoll 也是实现“遍历”可用通道的方式不同而已。select 使用轮询的方式,有 1024 个连接的限制,poll 去掉了这个限制依然是轮询的方式,epoll 是基于系统的注册回调的方式,监听系统的事件实现。

  5. NIO 引入了 Buffer 的概念,每次使用 Buffer 拷贝数据其实是一次从用户空间(JVM) 向系统空间(系统内存) 的一次拷贝, Java 里面提供了 DirectByteBuffer 堆外内存,如果使用使用堆外内存,可以减少一次系统空间和用户空间的拷贝,这种现象叫做零拷贝。强调一下,并不是操作系统不能直接操作 HeapByteBuffer(对内内存),而且在 GC 的作用下,内存地址可能随时变化,操作的内存数据不一定准备。

  6. IO 多路复用性能更好,针对的 I/O 密集型应用程序,如果是 CPU 密集型应用程序,还是通过多线程的方案。所以很多写 IO 多路复用的文章都会说“多线程的创建,必然存在创建销毁和切换的开销,在高并发系统中,会拖慢整个系统”,其实并不是非常的准确,虽然是想说明 I/O 多路复用的利好,但是确实有点以偏概全。

AIO:21 世纪非智能时代大学生把妹

21 世纪初期,还没有智能机,不过诺基亚 1110 砸核桃神机已经普及了,下面就是新时代大学生小王用自己的诺基亚 1110 的把妹过程。
小王给中意的两个女生直接发短信留言(群发):

小王 -> 女 A:下午一起看个电影?[早晨 10 点]
小王 -> 女 B:下午一起看个电影?[早晨 10 点]

发完短信小王去看《西游记》去了。10分钟以后电话响起,收到了妹子的短信,小王拿起了手机阅读了消息并进行回复。

女 B -> 小王:好呀,下午 3 点来我家接我吧 [早晨 10 点 10 分]
小王 -> 女 B:好的,我去接你不见不散。

名词解释

  1. 小王发完短信不需要盯着手机看,也不需要时不时看一下手机,有短信回复会有通知,再来阅读就好了。这就是 AIO 中的 AsynchronousServerSocketChannel,可以注册一个回调 CompletionHandler,等待有消息的时候直接通知回调处理即可。

优缺点

AIO 包括了 NIO 的所有优缺点的同时,增加了异步回调的能力,由此解决的问题是不需要同步的等待非阻塞 IO 的反馈,所以 NIO 叫做异步非阻塞 IO 模型。

是时候展示真正的技术了

说了这么多,用 NIO 实现一个把妹聊天程序呗?

服务器端

public class NioServer {public void start() throws IOException {Selector selector = Selector.open();ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();serverSocketChannel.bind(new InetSocketAddress(6789));serverSocketChannel.configureBlocking(false);serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);System.out.println("服务器启动成功");while (true) {selector.select();Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator<SelectionKey> iterator = selectionKeys.iterator();while (iterator.hasNext()) {SelectionKey selectionKey = iterator.next();if (selectionKey.isAcceptable()) {iterator.remove();handleAccept(serverSocketChannel, selector);} else if (selectionKey.isReadable()) {handleRead(selectionKey);} else {System.out.println("其他请求");}}}}private void handleRead(SelectionKey selectionKey) throws IOException {SocketChannel socketChannel = (SocketChannel) selectionKey.channel();ByteBuffer byteBuffer = ByteBuffer.allocate(1024);StringBuilder request = new StringBuilder();while (socketChannel.read(byteBuffer) > 0) {byteBuffer.flip();request.append(StandardCharsets.UTF_8.decode(byteBuffer));}if (request.length() > 0) {System.out.println("服务端收到消息:" + request.toString());}}private void handleAccept(ServerSocketChannel serverSocketChannel, Selector selector) throws IOException {SocketChannel socketChannel = serverSocketChannel.accept();socketChannel.configureBlocking(false);socketChannel.register(selector, SelectionKey.OP_READ);System.out.println("有新人进入聊天室");socketChannel.write(StandardCharsets.UTF_8.encode("进入聊天室,现在可以聊天了"));}public static void main(String[] args) throws IOException {new NioServer().start();}
}

客户端

public class NioClient {public void start() throws IOException {SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(6789));Selector selector = Selector.open();socketChannel.configureBlocking(false);socketChannel.register(selector, SelectionKey.OP_READ);new Thread(new NioClientHandler(selector)).start();Scanner scanner = new Scanner(System.in);while (scanner.hasNextLine()) {String request = scanner.nextLine();if (request != null && request.length() > 0) {socketChannel.write(StandardCharsets.UTF_8.encode(request));}}}public static void main(String[] args) throws IOException {new NioClient().start();}private class NioClientHandler implements Runnable {private Selector selector;public NioClientHandler(Selector selector) {this.selector = selector;}@Overridepublic void run() {try {while (true) {selector.select();Set<SelectionKey> selectionKeys = selector.selectedKeys();Iterator iterator = selectionKeys.iterator();while (iterator.hasNext()) {SelectionKey selectionKey = (SelectionKey) iterator.next();SocketChannel socketChannel = (SocketChannel) selectionKey.channel();ByteBuffer byteBuffer = ByteBuffer.allocate(1024);StringBuilder response = new StringBuilder();while (socketChannel.read(byteBuffer) > 0) {byteBuffer.flip();response.append(StandardCharsets.UTF_8.decode(byteBuffer));}if (response.length() > 0) {System.out.println("接收服务端消息:" + response);}}}} catch (Exception e) {e.printStackTrace();}}}
}

参考文档

  1. 图解 | 深入揭秘 epoll 是如何实现 IO 多路复用的!

  2. 解锁网络编程之NIO的前世今生

  3. NIO如何实现多路复用?

  4. 深入理解 Java IO

  5. 高并发专题之 IO 多路复用:Select、Poll、Epoll

推荐文章
  • 面试官问:前后端分离项目,有什么优缺点?我说:没

  • 2020 年腾讯新增 20 亿行代码,鹅厂第一编程语言还是它

  • 通俗讲解分布式锁,看完不懂算我输

  • 写博客能月入10K?

  • 一款基于 Spring Boot 的现代化社区(论坛/问答/社交网络/博客)

更多项目源码
  • 这或许是最美的Vue+Element开源后台管理UI

  • 推荐一款高颜值的 Spring Boot 快速开发框架

  • 一款基于 Spring Boot 的现代化社区(论坛/问答/社交网络/博客)

  • 13K点赞都基于 Vue+Spring 前后端分离管理系统ELAdmin,大爱

  • 想接私活时薪再翻一倍,建议根据这几个开源的SpringBoot项目

这篇关于第一次听人用男女关系讲 N(Non-Blocking)I(进)O(出),涨姿势了的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/495413

相关文章

C++中第一次听到构造函数

在C++中第一次听到构造函数这个名词,在C#中又遇到了。   在创建某个类时,由于对该对象的状态(数据)不是很明确,因此需要对其进行初始化。比如说我们要在长方形这个类中创建一个对象,或者说新建一个长方形,那么我们首先要确定他的长和宽,假如我们无法确定它的长和宽,那么我们是无法造出一个长方形来的。所以就要使用这个长方形类中一个用来构造该类所有对象的函数--构造函数。由于该函数要在创建一个新对象

我的第一次份实习工作-iOS实习生-第三个月

第三个月 这个月有一个考核项目,是一个电子书阅读器,组长说很重要,是我的实习考核项目。 我的项目XTReader,这是我参考网上的一些代码,和模仿咪咕阅读做的,功能还不完善,数据的部分是用聚合数据做的。要收费的。   还有阅读页面,基本功能实现了一下。使用了autolayout,自适应布局,也是第一次用网络,第一次用数据库,第一次用自动布局。还有很多不足。 做了一周多,有个问题一直没

我的第一次份实习工作-iOS实习生-公司使用过的软件

bittorrentsync 素材,文件同步软件 cornerstone svn 软件开发合作 mark man 测量坐标的软件 SQLLite Manager 数据库操作软件

我的第一次份实习工作-iOS实习生-第二个月

第二个月 来公司过了一个月了。每天早上9点上班,到晚上6.30下班,上下班要指纹打卡,第一个月忘了打卡好多次(),然后还要去补打卡单。公司这边还安排了,工资卡办理,招商银行卡。开了一次新员工大会,认识了公司的一些过往,公司的要求等,还加了一下公司的企业QQ,还有其他的羽毛球群,篮球群。我加了下羽毛球群,也去打了一两次。第二个月的感受,感觉跟组里面的交流跟沟通都好少,基本上还有好多人不认识。想想也

我的第一次份实习工作-iOS实习生-第一个月

实习时间:2015-08-20 到 2015-12-25  实习公司;福建天棣互联有限公司 实习岗位:iOS开发实习生 第一个月: 第一天来公司,前台报道后,人资带我去我工作的地方。到了那,就由一个组长带我,当时还没有我的办公桌,组长在第三排给我找了一个位置,擦了下桌子,把旁边的准备的电脑帮我装了下,因为学的是iOS,实习生就只能用黑苹果了,这是我实习用的电脑。 帮我装了一下电脑后,开机

HDU1720(输入输出涨姿势)

A+B Coming Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 5953    Accepted Submission(s): 3901 题目链接: http://acm.hdu.edu.cn/showproblem.p

第一次上传代码到github

1 注册一个github账户 2 最好再设置一个ssh免密设置:http://java-holding.iteye.com/blog/2355969 3 设置好2步骤之后就可以直接不需要输入用户名密码进行上传和下载代码的操作了 4 第一次上传代码到github中的我认为最简单省事的办法:   a、在github上创建一个仓库,如下图所示:               按照步骤新建一个远程仓库之后

Apache Flink:Keyed Window与Non-Keyed Window

Apache Flink中,Window操作在流式数据处理中是非常核心的一种抽象,它把一个无限流数据集分割成一个个有界的Window(或称为Bucket),然后就可以非常方便地定义作用于Window之上的各种计算操作。本文我们主要基于Apache Flink 1.4.0版本,说明Keyed Window与Non-Keyed Window的基本概念,然后分别对与其相关的WindowFunction

剑指offer——第一次只出现一次的字符

/*** */package interview35;/*** 第一次只出现一次的字符* 在一个字符串(1<=字符串长度<=10000,全部由大写字母组成)中找到第一个只出现一次的字符,并返回它的位置*@author: Administrator*@date: 2017-1-9 下午07:34:07*/import java.util.Scanner;public class Solutio

【Flutter】解决第一次运行项目很慢(gradle需要下载依赖)

配置gradle默认下载路径 默认下C盘谁顶得住 配置环境变量 名称: GRADLE_USER_HOME 值: D:\Develop\gradle 自己创建一个 下边是重点 配置gradle远端下载地址 后边版本号自己换 https://mirrors.cloud.tencent.com/gradle/ https://mirrors.cloud.tencent.com/gradle/g