Subject

简介: Subject Subject可以看成是一个桥梁或者代理,在某些ReactiveX实现中(如RxJava),它同时充当了Observer和Observable的角色。因为它是一个Observer,它可以订阅一个或多个Observable;又因为它是一个Observable,它可以转发它收到(Observe)的数据,也可以发射新的数据。 由于一个Subject订阅一个Obse

Subject

Subject可以看成是一个桥梁或者代理,在某些ReactiveX实现中(如RxJava),它同时充当了Observer和Observable的角色。因为它是一个Observer,它可以订阅一个或多个Observable;又因为它是一个Observable,它可以转发它收到(Observe)的数据,也可以发射新的数据。

由于一个Subject订阅一个Observable,它可以触发这个Observable开始发射数据(如果那个Observable是"冷"的--就是说,它等待有订阅才开始发射数据)。因此有这样的效果,Subject可以把原来那个"冷"的Observable变成"热"的。

Subject的种类

针对不同的场景一共有四种类型的Subject。他们并不是在所有的实现中全部都存在,而且一些实现使用其它的命名约定(例如,在RxScala中Subject被称作PublishSubject)。

AsyncSubject

一个AsyncSubject只在原始Observable完成后,发射来自原始Observable的最后一个值。(如果原始Observable没有发射任何值,AsyncObject也不发射任何值)它会把这最后一个值发射给任何后续的观察者。 

然而,如果原始的Observable因为发生了错误而终止,AsyncSubject将不会发射任何数据,只是简单的向前传递这个错误通知。 

BehaviorSubject

当观察者订阅BehaviorSubject时,它开始发射原始Observable最近发射的数据(如果此时还没有收到任何数据,它会发射一个默认值),然后继续发射其它任何来自原始Observable的数据。 

然而,如果原始的Observable因为发生了一个错误而终止,BehaviorSubject将不会发射任何数据,只是简单的向前传递这个错误通知。 

PublishSubject

PublishSubject只会把在订阅发生的时间点之后来自原始Observable的数据发射给观察者。需要注意的是,PublishSubject可能会一创建完成就立刻开始发射数据(除非你可以阻止它发生),因此这里有一个风险:在Subject被创建后到有观察者订阅它之前这个时间段内,一个或多个数据可能会丢失。如果要确保来自原始Observable的所有数据都被分发,你需要这样做:或者使用Create创建那个Observable以便手动给它引入"冷"Observable的行为(当所有观察者都已经订阅时才开始发射数据),或者改用ReplaySubject。 

如果原始的Observable因为发生了一个错误而终止,PublishSubject将不会发射任何数据,只是简单的向前传递这个错误通知。 

ReplaySubject

ReplaySubject会发射所有来自原始Observable的数据给观察者,无论它们是何时订阅的。也有其它版本的ReplaySubject,在重放缓存增长到一定大小的时候或过了一段时间后会丢弃旧的数据(原始Observable发射的)。

如果你把ReplaySubject当作一个观察者使用,注意不要从多个线程中调用它的onNext方法(包括其它的on系列方法),这可能导致同时(非顺序)调用,这会违反Observable协议,给Subject的结果增加了不确定性。

RxJava的对应类

假设你有一个Subject,你想把它传递给其它的代理或者暴露它的Subscriber接口,你可以调用它的asObservable方法,这个方法返回一个Observable。具体使用方法可以参考Javadoc文档。

串行化

如果你把 Subject 当作一个 Subscriber 使用,注意不要从多个线程中调用它的onNext方法(包括其它的on系列方法),这可能导致同时(非顺序)调用,这会违反Observable协议,给Subject的结果增加了不确定性。

要避免此类问题,你可以将 Subject 转换为一个 <a rel="nofollow" href="http://reactivex.io/RxJava/javadoc/rx/subjects/SerializedSubject.html" "="" style="box-sizing: border-box; color: rgb(45, 133, 202); text-decoration: none; background-color: transparent;">SerializedSubject ,类似于这样:

mySafeSubject = new SerializedSubject( myUnsafeSubject );
目录
相关文章
|
安全 API 测试技术
shiro实战系列(十)之Subject
毫无疑问,在 Apache Shiro 中最重要的概念就是 Subject。'Subject'仅仅是一个安全术语,是指应用程序用户的特定 安全的“视图”。一个 Shiro Subject 实例代表了一个单一应用程序用户的安全状态和操作。
1610 0
使用JdbcRealm时,UnauthorizedException: Subject does not have permission
使用JdbcRealm时,UnauthorizedException: Subject does not have permission
邮件(email)
邮件–发送邮件 1.准备工作 1.1.生成查长度为4的验证码
105 0
|
缓存 安全 UED
RxJava 的 Subject
RxJava 的 Subject
103 0
Rxjs 里 Subject 和 BehaviorSubject 的区别
Rxjs 里 Subject 和 BehaviorSubject 的区别
148 0
Rxjs 里 Subject 和 BehaviorSubject 的区别
|
存储 调度
RxJs Subject, AnonymousSubject, BehaviorSubject, ReplaySubject和AsyncSubject
RxJs Subject, AnonymousSubject, BehaviorSubject, ReplaySubject和AsyncSubject
107 0
RxJs Subject, AnonymousSubject, BehaviorSubject, ReplaySubject和AsyncSubject
workflow and email in QD3 - IS_INBOX_USER method
workflow and email in QD3 - IS_INBOX_USER method
workflow and email in QD3 - IS_INBOX_USER method
谋杀 Email
作为新来者,凭着技术的进步、企业提升效率的需求、大厂们留下的中小客户市场切口,Zoom、Slack们高歌猛进,抢夺“Email们”的市场,在“WinTel大厂”们没能涉足的市场切下一块蛋糕。但在未来,当深入到大厂腹地,深入大型客户市场,新老企服软件公司的一战似乎不可避免。面对这些老玩家,他们能成功么
223 0
JavaUtil_09_email_使用 commons-email 发送邮件
  二、参考资料 1.【commons】邮件发送工具——commons-email
1044 0