惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

freeCodeCamp Programming Tutorials: Python, JavaScript, Git & More
爱范儿
爱范儿
WordPress大学
WordPress大学
博客园 - 三生石上(FineUI控件)
J
Java Code Geeks
Vercel News
Vercel News
aimingoo的专栏
aimingoo的专栏
T
Tailwind CSS Blog
罗磊的独立博客
B
Blog
博客园_首页
A
About on SuperTechFans
有赞技术团队
有赞技术团队
V
V2EX
U
Unit 42
I
InfoQ
IT之家
IT之家
博客园 - 司徒正美
阮一峰的网络日志
阮一峰的网络日志
博客园 - 叶小钗
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
Stack Overflow Blog
Stack Overflow Blog
The Cloudflare Blog
H
Help Net Security

一个工匠

AI 发展临界点 - 快上车 流式响应(Chat):HTTP 响应体字节流的读取与解析 iPhone 截屏高效翻译 Flash Open Terminal iPhone 侧载安装 Xcode Symbolic Debug AI 指北 投资风险收益评估 Mac 快速修改系统快捷键 Git Record passkey How to pay apple frameworks Mac - Command Line Tools DNS 的 CNAME 是如何工作的 WebRTC 的一些解释 SSE 指南 1.1.1.1、WARP 和 MASQUE 移动端换端方案与场景还原 设备发现 分辨率 - 像素密度 - HiDPI Mac 字体 ESP32 trump - 川普 币圈 - 虚拟货币 【旅游】富士山 【旅游】sakura(樱花) 【旅游】千岛湖 我的 2023 【Swift】中文词语纠错
谈谈事件驱动
海驴 · 2018-11-08 · via 一个工匠

事件驱动这个技术方案,可以说实实在在影响了这些年编程界的技术方向。最实际的受用者应该就是异步编程了,如 I / O。

我所认知到的语言,都是事件驱动的使用者,受益者,推动者。

很多朋友可能更多的停留在精通官方 API 阶段,还没有更深层次的认知计算机原理,不晓得代码是怎么工作的。我不精通官方 API,计算机原理也认知浅薄,但在自己认知的语言范围内了解了一些。我感到庆幸,希望和大家分享。

事件驱动的形象描述

A 和家人去外婆家取了个号。A 一直在门口等着,是阻塞。A 出去玩一会,门分钟去外婆家门口看看到了自己号没有,是监听。A 去一个衣服店看衣服去了,到了自己号的时候,收到外婆家发的短信消息后直接去外婆家,是回调。

上面这个例子,变种极多也千篇一律。串行并行、同步异步、阻塞非阻塞都可以用。我们用这个例子来说事件驱动

这里分析第三种情况,A 去看衣服去了,这个时候外婆家的号叫到自己,并短信通知了自己,这个行为的分析。

A 查看短信的行为和外婆家发出短信的行为,就是我们分析的重点。

外婆家为了发出这个短信,需要耗时,甚至外婆家也不知道耗时多久。所以外婆家需要做的是,一定要在 A 的号到了的时候,准确及时的发出短信,这是一个事件的发出。

A 虽然有手机,但是看不看短信是 A 的事情。所以 A 一定要在看到短信之后立即作出处理判断,这是一个事件的反馈。

但是 A 为了能够尽快吃到饭,多做了几手准备,他把西贝、海底捞几家店的号都拿了,打算谁先叫到自己,就去谁家。

所以 A 接受到的事件是多个并且不确定的。

Life is thread,我们把 A 比作一个线程。A 能够及时响应各家店面发来的消息,原因就是线程里面有一个while (true):{pass;}这样的循环。依靠 CPU 这个超强大脑控制器,只要有事件需要通知到线程,线程里面的这个 while 循环就会获取到并及时处理。

所以事件驱动的本质是:一方及时发出事件,通过 CPU 时间片实时轮转事件循环队列并告知到 while 循环以通知到另一方,另一方及时响应事件。

iOS 中的使用

Runloop

Runloop可以说把事件驱动利用到了极致。你能想象,如果没有Runloop,你就真的不能使用 iPhone 手机了!
Runloop依托于线程。我们手势点击一个按钮,就是在操作主线程里的Runloop
Runloop通过事件驱动在以下 8 种状态下实时循环切换,用于省电的同时又能够及时处理用户界面反馈。

1
2
3
4
5
6
7
8
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
kCFRunLoopEntry = (1UL << 0), // 即将进入Loop
kCFRunLoopBeforeTimers = (1UL << 1), // 即将处理 Timer
kCFRunLoopBeforeSources = (1UL << 2), // 即将处理 Source
kCFRunLoopBeforeWaiting = (1UL << 5), // 即将进入休眠
kCFRunLoopAfterWaiting = (1UL << 6), // 刚从休眠中唤醒
kCFRunLoopExit = (1UL << 7), // 即将退出Loop
};
闭包

我们通过 IOS 里的Block闭包,可以在异步执行一串功能逻辑代码后接着处理闭包里的活。

1
- (void)someMethodThatTakesABlock:(returnType (^nullability)(parameterTypes))blockName;
1
[someObject someMethodThatTakesABlock:^returnType (parameters) {...}];
还有其他非常多的使用,如通知等

Python 中的使用

Python 近些年才完全开发完优秀的协程并开放使用。使得 Python 上多并发成为事实上的可能。这里的多,不是之前的几十几百,是上十万。

Event_loop+协程

Python 里面使用多线程其实并不怎么爽,本身就是耗资源的语言,多线程切换更加雪上加霜了。通过协程,妥妥的解决了上十万的并发。

1
2
3
4
5
6
7
8
9
import asyncio
async def test(i):
print("test_1",i)
await asyncio.sleep(1)
print("test_2",i)
loop=asyncio.get_event_loop()
tasks=[test(i) for i in range(5)]
loop.run_until_complete(asyncio.wait(tasks))
loop.close()
aiohttp

网络访问上的多并发,对协程的进一步封装。

Node.js 中的使用

Event_loop事件循环

这个就没得说了,彻彻底底依靠事件驱动起家的语言。基于javascriptV8引擎起来的 Node.js,就是完完全全的单线程语言。
可是要知道,Node.js 就是以单线程中使用事件驱动处理高 IO 闻名世界的。
你可以想象一下,一个 Node.js 搭建的后台,每秒上千上万的并发,都是单线程在处理吗?
Java 就是一个用户一个请求一个线程(又名线程驱动),服务器资源耗费真的大。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
var fs = require("fs");
var debug = require('debug')('example1');

debug("begin");

fs.readFile('package.json','utf-8',function(err,data){
if(err)
debug(err);
else
debug("get file content");
});

setTimeout(function(){
debug("timeout2");
});

debug('end');