搜公众号
推荐 原创 视频 Java开发 开发工具 Python开发 Kotlin开发 Ruby开发 .NET开发 服务器运维 开放平台 架构师 大数据 云计算 人工智能 开发语言 其它开发 iOS开发 前端开发 JavaScript开发 Android开发 PHP开发 数据库
Lambda在线 > 一名打字员 > 观察者模式中的线程安全

观察者模式中的线程安全

一名打字员 2018-05-14
举报

简单说两句

这篇文字写了好久勒,就是不敢发出来,因为有的措辞以及描述并不是很规范,但最后还是发了出来,一起找茬,毕竟有错误才能有进步。

实现过程

  • 命名规则

之前我们实现的简单的观察者模式,是直接的出现了subject、observer这种字眼,然而实际的应用之中,会很少出现这种命名,一般都是根据出现的场景进行具体的命名。

监听器的命名则会跟着Listener后缀,当我们需要注册多个类型的监听器的时候,一般我们会用update前缀,但是本打字员还是推荐使用on前缀,比较通俗易懂。是不是细心的童鞋又发现了,在工作中设置安卓点击监听onClickListener或者onItemClickLitenr等等的时候这些函数名都很眼熟,没错,安卓这里也用到了观察者。

  • 线程安全

上一篇文章我们简单的用Java语言实现了观察者模式,但是在多线程中,如何保证其在修改注册监听的时候不会发生线程冲突保证安全呢,我们可以依次从下面几点来解决这个问题。

  1. 监听器集合资源竞争

我们可以简单的利用Java的同步机制来解决这个问题,当一个线程尝试添加一个新的监听器的时候,另一线程又尝试添加一个新的被观察者对象,这个时候所有注册的监听器就会发出通知,我们可以在添加监听的时候加上synchronized关键字,这样一来,只有一个线程能在同一时刻修改或者访问监听器的列表。

但是,只要没有监听器撤销或者是注册的情况下,多个通知也就是读操作是可以被允许的,我们可以设计一个读写锁用来分开管理读写操作的资源锁定。

  1. 监听器的并发访问

监听器的并发访问可以通过保证监听器的线程安全来实现,所以我们只需要在监听器类的内部实现线程安全就行了。

  1. 监听器的有序通知

很多时候我们需要监听器有序执行,这个时候就不能够通过读写锁了,需要再引入一个新的机制,可以保证通知函数的顺序和添加监听的顺序保持一致,我们可以按照现金先出的顺序获得读写锁的权限,总体采用公平有序方式,线程A在完成注册操作或者撤销操作的时候,线程B在操作之后尝试通知已注册的监听器,线程C在等待只读锁的同时也尝试通知已注册的监听器。

关于观察者模式还有很多值得去深究的地方,我们在开发的时候应该注意:

监听器启动新线程。新线程启动后,在新线程中执行监听器逻辑的同时,返回监听器函数的处理结果,并运行其他监听器执行。

Subject启动新线程。与传统的线性迭代已注册的监听器列表不同,Subject的notify函数重启一个新的线程,然后在新线程中迭代监听器列表。这样使得notify函数在执行其他监听器操作的同时可以输出其返回值。需要注意的是需要一个线程安全机制来确保监听器列表不会进行并发修改。

队列化监听器调用并采用一组线程执行监听功能。将监听器操作封装在一些函数中并队列化这些函数,而非简单的迭代调用监听器列表。这些监听器存储到队列中后,线程就可以从队列中弹出单个元素并执行其监听逻辑。这类似于生产者-消费者问题,notify过程产生可执行函数队列,然后线程依次从队列中取出并执行这些函数,函数需要存储被创建的时间而非执行的时间供监听器函数调用。

写在最后

最近比较忙,发生的事情比较多,愿大家都有一个好心情去撸码。


版权声明:本站内容全部来自于腾讯微信公众号,属第三方自助推荐收录。《观察者模式中的线程安全》的版权归原作者「一名打字员」所有,文章言论观点不代表Lambda在线的观点, Lambda在线不承担任何法律责任。如需删除可联系QQ:516101458

文章来源: 阅读原文

相关阅读

关注一名打字员微信公众号

一名打字员微信公众号:alittercoder

一名打字员

手机扫描上方二维码即可关注一名打字员微信公众号

一名打字员最新文章

精品公众号随机推荐

举报