内容简介:最近两天被极客时间的新课刷群刷屏。刷屏的标题大多是“学了这么多年 Java,却连 singleton 都不会用”、“面试总被问高并发,你真的会么”这一类标题党。内容千篇一律是推荐极客时间打新的课程,《Java 并发编程实战》。高并发哥又不是没做过,随手找了一下,发现陈皓在 2009 年的一篇文章就提到了正确的解法,以及背后的原因。《文中给出几种功能上正确的 singleton 写法。
最近两天被极客时间的新课刷群刷屏。刷屏的标题大多是“学了这么多年 Java,却连 singleton 都不会用”、“面试总被问高并发,你真的会么”这一类标题党。内容千篇一律是推荐极客时间打新的课程,《Java 并发编程实战》。
高并发哥又不是没做过,随手找了一下,发现陈皓在 2009 年的一篇文章就提到了正确的解法,以及背后的原因。《 深入浅出单实例 SINGLETON 设计模式 》。
文中给出几种功能上正确的 singleton 写法。
// version 1.4 public class Singleton { private volatile static Singleton singleton = null; private Singleton() {} public static Singleton getInstance() { if (singleton == null) { synchronized (Singleton.class) { if (singleton== null) { singleton= new Singleton(); } } } return singleton; } }
请留意私有变量的描述词 volatile
,目的是不让编译器对指令进行重 排序 优化。
// version 1.5 public class Singleton { private volatile static Singleton singleton = new Singleton(); private Singleton() {} public static Singleton getInstance() { return singleton; } }
这是自动加载版本。每次加载类的时候,实例就生成了。所以加载类的过程可能会很慢(特别是有很多继承、引用的情况)。
// version 1.6 public class Singleton { private static class SingletonHolder { private static final Singleton INSTANCE = new Singleton(); } private Singleton() {} public static final Singleton getInstance() { return SingletonHolder.INSTANCE; } }
这是对上面 1.5 版本的修正。 SingletonHolder
是个私有类,并且在 Singleton
加载的时候才会被调用, INSTANCE
才会被真正创建。
这段代码是即确保了线程安全,又实现了懒加载的较优办法。
还有一个所谓最优(优雅?代码最少?)的办法,不过不建议大家使用,可读性实在不太高。有点奇技淫巧的意思,大大牺牲了代码的可读性。
public enum Singleton{ INSTANCE; }
利用了 enum
的创建是线程安全这一特性。
PS:PHP 中没有 singleton 的困扰,因为 php 语言特点决定的。php-fpm 本身就是 accepter-worker 并发模式,程序员写的 PHP 程序其实只是 worker,worker 与 worker 之间由 fpm 完成资源隔离和协调,PHP 程序员并不需要从内存数据的层面考虑并发的情况。所以有句话讲得不错, singleton 在 PHP 语言中不是一个好实践(practice) 。PHP 的 singleton 用简单的工厂模式就够了。
今天抽空找了下 MQTT 的 QoS2 实现方式,记录如下。原科普文链接《 MQTT QoS 深度解读 》。
无论是 QoS2 还是 transaction,原理都是一样的: 通过一次代价非常小、成功概率足够高的操作,作为最后确认的依据 。这样做并不是说绝对不出错,而是出错的概率足够低,实践中可以忽略。
sequenceDiagram participant Publisher participant Broker participant Subscriber Publisher->>Publisher: Store(Msg) Publisher->>Broker: PUBLISH(QoS2, Msg) Broker->>Broker: Store(Msg) Broker->>Publisher: PUBREC Publisher->>Broker: PUBREL Broker->>Subscriber: PUBLISH(QoS2, Msg) Broker->>Publisher: PUBCOMP Publisher->>Publisher: Delete(Msg) Subscriber->>Subscriber: Store(Msg) Subscriber->>Broker: PUBREC Broker->>Subscriber: PUBREL Subscriber->>Subscriber: Notify(Msg) Subscriber->>Broker: PUBCOMP Broker->>Broker: Delete(Msg) Subscriber->>Subscriber: Delete(Msg)
简单一点的模型,如果不需要中间的 broker,则流程如下。
sequenceDiagram participant Publisher participant Subscriber Publisher->>Publisher: Store(Msg) Publisher->>Subscriber: (1) PUBLISH(QoS2, Msg) Subscriber->>Subscriber: Store(Msg) Subscriber->>Publisher: (2) PUBREC Publisher->>Subscriber: (3) PUBREL Subscriber->>Subscriber: Notify(Msg) Subscriber->>Publisher: (4) PUBCOMP Subscriber->>Subscriber: Delete(Msg) Publisher->>Publisher: Delete(Msg)
从简化以后的模型可以看到,publisher 和 subscriber 有两次交互。第一次,publisher 把 msg 推送给 subscriber,对应 PUBLISH
/ PUBREC
指令。第二次,publisher 等于是询问 subscriber,“你是不是收到一次”,对应 PUBREL
/ PUBCOMP
指令。
如果没有第 (3)/(4)步, PUBREL
/ PUBCOMP
指令,实际就是 QoS1, 至少收到一次
。
再少一点,如果没有 (2)/(3)/(4) 步,只剩第 (1) 步,实际就是 QoS0, 至多只发送一次 。
科普文里面提问,为什么 MQTT QoS2 是两次“握手”,而不是像 TCP 一样,三次握手。我觉得这个问题太教条了。为什么 negotiate 就一定要想到 TCP 呢?当然,如果一定要回答,最本质的区别就是,MQTT QoS2 通讯是单向的,而 TCP 连接的通讯是双向的。单向的只需要一方取信于另外一方即可,而双向通讯需要两方都取信于对方。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网
猜你喜欢:- 用技术解决“非技术”问题
- 数据安全治理重要相关技术——脱敏技术
- 零信任技术进阶篇:关键技术及挑战
- 零信任技术进阶篇:关键技术及挑战
- 2021 技术展望 | 走向未来的实时生成技术
- 前端技术演进(一):Web前端技术基础
本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们。
精彩绝伦的CSS
[美] Eric A. Meyer / 姬光 / 人民邮电出版社 / 2012-7 / 49.00元
内容简介: 打造现代布局的专业技术 本书远非只是介绍基础知识,它不仅全面细致地讲解布局与效果,而且展望了HTML5和CSS3的未来。业内很少有人能像Eric A. Meyer一样详细阐明CSS,他在本书中深入分析了普遍适用的实用技术,讲解了如何选用正确的工具、如何通过jQuery使用CSS效果和CSS3技术。 本书主要内容如下: 显示或隐藏元素 通过XHTML为bod......一起来看看 《精彩绝伦的CSS》 这本书的介绍吧!