热信号:事件触发;

冷信号:订阅出发;

从本质上来说,是信号的存在和产生,是静态信号和动态信号的区别。

背景

ReactiveCocoa(简称RAC)是最初由GitHub团队开发的一套基于Cocoa的FRP框架。FRP即Functional Reactive Programming(函数式响应式编程),其优点是用随时间改变的函数表示用户输入,这样就不需要可变状态了。我们之前的文章“RACSignal的Subscription深入分析”里曾经详细讲解过RAC核心概念之一RACSignal的实现原理。在美团客户端中,我们大量使用了这个框架。冷信号与热信号的概念很容易混淆并造成一定的问题。鉴于这个问题具有一定普遍性,我将用一系列文章讲解RAC中冷信号与热信号的相关知识点,希望可以加深大家的理解。本文是系列文章的第一篇。

p.s. 以下代码和示例基于ReactiveCocoa v2.5

什么是冷信号与热信号

冷热信号的概念源于.NET框架Reactive Extensions(RX)中的Hot Observable和Cold Observable,两者的区别是:

  1. Hot Observable是主动的,尽管你并没有订阅事件,但是它会时刻推送,就像鼠标移动;而Cold Observable是被动的,只有当你订阅的时候,它才会发布消息。

  2. Hot Observable可以有多个订阅者,是一对多,集合可以与订阅者共享信息;而Cold Observable只能一对一,当有不同的订阅者,消息是重新完整发送。

这里面的Observables可以理解为RACSignal。为了加深理解,我们来看这样的几组代码:

    RACSignal *signal = [RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[subscriber sendNext:@1];
[subscriber sendNext:@2];
[subscriber sendNext:@3];
[subscriber sendCompleted];
return nil;
}];
NSLog(@"Signal was created.");
[[RACScheduler mainThreadScheduler] afterDelay:0.1 schedule:^{
[signal subscribeNext:^(id x) {
NSLog(@"Subscriber 1 recveive: %@", x);
}];
}]; [[RACScheduler mainThreadScheduler] afterDelay:1 schedule:^{
[signal subscribeNext:^(id x) {
NSLog(@"Subscriber 2 recveive: %@", x);
}];
}];

以上简单地创建了一个信号,并且依次发送@1,@2,@3作为值。下面分别有两个订阅者在不同的时间段进行了订阅,运行的结果如下:

2015-08-11 18:33:21.681 RACDemos[6505:1125196] Signal was created.
2015-08-11 18:33:21.793 RACDemos[6505:1125196] Subscriber 1 recveive: 1
2015-08-11 18:33:21.793 RACDemos[6505:1125196] Subscriber 1 recveive: 2
2015-08-11 18:33:21.793 RACDemos[6505:1125196] Subscriber 1 recveive: 3
2015-08-11 18:33:22.683 RACDemos[6505:1125196] Subscriber 2 recveive: 1
2015-08-11 18:33:22.683 RACDemos[6505:1125196] Subscriber 2 recveive: 2
2015-08-11 18:33:22.683 RACDemos[6505:1125196] Subscriber 2 recveive: 3

我们可以看到,信号在18:33:21.681时被创建,18:33:21.793依次接到1、2、3三个值,而在18:33:22.683再依次接到1、2、3三个值。说明了变量名为signal的这个信号,在两个不同时间段的订阅过程中,分别完整地发送了所有的消息。

我们再对这段代码进行一个小的改动:

    RACMulticastConnection *connection = [[RACSignal createSignal:^RACDisposable *(id<RACSubscriber> subscriber) {
[[RACScheduler mainThreadScheduler] afterDelay:1 schedule:^{
[subscriber sendNext:@1];
}]; [[RACScheduler mainThreadScheduler] afterDelay:2 schedule:^{
[subscriber sendNext:@2];
}]; [[RACScheduler mainThreadScheduler] afterDelay:3 schedule:^{
[subscriber sendNext:@3];
}]; [[RACScheduler mainThreadScheduler] afterDelay:4 schedule:^{
[subscriber sendCompleted];
}];
return nil;
}] publish];
[connection connect];
RACSignal *signal = connection.signal; NSLog(@"Signal was created.");
[[RACScheduler mainThreadScheduler] afterDelay:1.1 schedule:^{
[signal subscribeNext:^(id x) {
NSLog(@"Subscriber 1 recveive: %@", x);
}];
}]; [[RACScheduler mainThreadScheduler] afterDelay:2.1 schedule:^{
[signal subscribeNext:^(id x) {
NSLog(@"Subscriber 2 recveive: %@", x);
}];
}];

稍微有些复杂,我们来一一分析:

  • 创建了一个信号,在1秒、2秒、3秒分别发送1、2、3这三个值,4秒发送结束信号。
  • 对这个信号调用publish方法得到一个RACMulticastConnection。
  • 让connection进行连接操作。
  • 获得connection的信号。
  • 分别在1.1秒和2.1秒订阅获得的信号。

抛开RACMulticastConnection是个什么东东,我们先来看下结果:

2015-08-12 11:07:49.943 RACDemos[9418:1186344] Signal was created.
2015-08-12 11:07:52.088 RACDemos[9418:1186344] Subscriber 1 recveive: 2
2015-08-12 11:07:53.044 RACDemos[9418:1186344] Subscriber 1 recveive: 3
2015-08-12 11:07:53.044 RACDemos[9418:1186344] Subscriber 2 recveive: 3

首先告诉大家- [RACSignal publish]- [RACMulticastConnection connect]- [RACMulticastConnection signal]这几个操作生成了一个热信号。
我们再来关注下输出结果的一些细节:

  • 信号在11:07:49.943被创建
  • 11:07:52.088时订阅者1才收到2这个值,说明1这个值没有接收到,时间间隔是2秒多
  • 11:07:53.044时订阅者1和订阅者2同时收到3这个值,时间间隔是3秒多

参考一开始的Hot Observables的论述和两段小程序的输出结果,我们可以确定冷热信号的如下特点:

  1. 热信号是主动的,即使你没有订阅事件,它仍然会时刻推送。如第二个例子,信号在50秒被创建,51秒的时候1这个值就推送出来了,但是当时还没有订阅者。而冷信号是被动的,只有当你订阅的时候,它才会发送消息。如第一个例子。
  2. 热信号可以有多个订阅者,是一对多,信号可以与订阅者共享信息。如第二个例子,订阅者1和订阅者2是共享的,他们都能在同一时间接收到3这个值。而冷信号只能一对一,当有不同的订阅者,消息会从新完整发送。如第一个例子,我们可以观察到两个订阅者没有联系,都是基于各自的订阅时间开始接收消息的。

好的,至此我们知道了什么是冷信号与热信号,了解了它们的特点。下一篇文章我们来看看为什么要区分冷信号与热信号。

https://tech.meituan.com/talk-about-reactivecocoas-cold-signal-and-hot-signal-part-1.html

细说ReactiveCocoa的冷信号与热信号(一)的更多相关文章

  1. ReactiveCocoa的冷信号与热信号 探讨

    背景 ReactiveCocoa(简称RAC)是最初由GitHub团队开发的一套基于Cocoa的FRP框架.FRP即Functional Reactive Programming(函数式响应式编程), ...

  2. ReactiveCocoa 中 RACSignal 是怎样发送信号

    前言 ReactiveCocoa是一个(第一个?)将函数响应式编程范例带入Objective-C的开源库.ReactiveCocoa是由Josh Abernathy和Justin Spahr-Summ ...

  3. ReactiveCocoa 中 RACSignal 是如何发送信号的

    https://juejin.im/post/5829f4c3570c350063c436ac 前言 ReactiveCocoa是一个(第一个?)将函数响应式编程范例带入Objective-C的开源库 ...

  4. Linux 信号详解六(可靠信号与不可靠信号)

    #include <stdio.h> #include <stdlib.h> #include <string.h> #include <unistd.h&g ...

  5. Linux 信号详解五(信号阻塞,信号未决)

    信号在内核中的表示 执行信号的处理动作成为信号递达(Delivery),信号从产生到递达之间的状态称为信号未决(Pending).进程可以选择阻塞(Block)某个信号. 被阻塞的信号产生时将保持在未 ...

  6. UNIX环境高级编程——可靠信号与不可靠信号

    在早期的UNIX中信号是不可靠的,不可靠在这里指的是:信号可能丢失,一个信号发生了,但进程却可能一直不知道这一点. 现在Linux 在SIGRTMIN实时信号之前的都叫不可靠信号,这里的不可靠主要是不 ...

  7. Linux信号实践(3) --信号内核表示

    信号在内核中的表示 执行信号的处理动作称为信号递达(Delivery),信号从产生到递达之间的状态,称为信号未决(Pending).进程可以选择阻塞(Block)某个信号.被阻塞的信号产生时将保持在未 ...

  8. OpenStack虚拟机冷迁移与热迁移

    一.虚拟机迁移分析 openstacvk虚拟机迁移分为冷迁移和热迁移两种方式. 1.1冷迁移: 冷迁移(cold migration),也叫静态迁移.关闭电源的虚拟机进行迁移.通过冷迁移,可以选择将关 ...

  9. 三十四、Linux 进程与信号——信号特点、信号集和信号屏蔽函数

    34.1 信号特点 信号的发生是随机的,但信号在何种条件下发生是可预测的 进程杠开始启动时,所有信号的处理方式要么默认,要么忽略:忽略是 SIGUSR1 和 SIGUSR2 两个信号,其他都采取默认方 ...

随机推荐

  1. poj_1185状压dp

    用二维数组写了好久,失败啊.. #include<iostream> #include<string.h> #include<cstdio> #include< ...

  2. No connection could be made because the target machine actively refused it [::1]:808

    No connection could be made because the target machine actively refused it [::1]:808 1.首先查看端口占用情况, 在 ...

  3. [JZOJ NOIP2018模拟10.20 B组]

    T1:原根(math) 题目链接: http://172.16.0.132/senior/#contest/show/2532/0 题目: 题解: 一个数m原根的个数是$\phi{(\phi{(m)} ...

  4. matlab张量工具初步

    最近从桑迪亚实验室下载了张量工具包.但是不太会用. 很多网上的方法, addpath(pwd) cd met; addpath(pwd) savepath M=ones(4,3,2); X=tenso ...

  5. Tomcat学习(一)——使用Eclipse绑定Tomcat并发布应用

    1.下载Tomcat 官网地址:http://tomcat.apache.org/whichversion.html 2.目录结构 bin:脚本目录 启动脚本:startup.bat 停止脚本:shu ...

  6. FCC高级编程篇之Exact Change

    Exact Change Design a cash register drawer function checkCashRegister() that accepts purchase price ...

  7. DELL inspiron 14-7467 进入安全模式方法

    您按住shift键不要松开,然后重启电脑,选择疑难解答-高级选项-启动设置-数字四 安全模式启动

  8. 爬虫来啦!Day91

    # 一.爬虫# 1.基本操作# 排名爬虫刷票# 抽屉网的所有发布新闻点赞# 自动化程序模拟用于的日常操作# 投票的机制是利用cookies,禁用cookies模式# 自定义的异步IO模块就是Socke ...

  9. luogu P1586 四方定理(背包)

    题意 题解 首先吐槽一下体面的第一句话.反正我不知道(可能是因为我太菜了) 可能没有睡醒,没看出来是个背包. 但告诉是个背包了应该就好做了. #include<iostream> #inc ...

  10. 平衡二叉树(AVLTREE,双链表实现)

    首先说下好久没更新了,最近打游戏和工作都有点多,o(^▽^)o. 写这个AVL发现自己的代码风格好差,尤其是变量命名这块,后来意识到了,想去改,但是太多了,改了几个就不想改了,做这个是记录下自己的成长 ...