不过时的技术

栏目: PHP · 发布时间: 5年前

内容简介:最近两天被极客时间的新课刷群刷屏。刷屏的标题大多是“学了这么多年 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 连接的通讯是双向的。单向的只需要一方取信于另外一方即可,而双向通讯需要两方都取信于对方。


以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持 码农网

查看所有标签

猜你喜欢:

本站部分资源来源于网络,本站转载出于传递更多信息之目的,版权归原作者或者来源机构所有,如转载稿涉及版权问题,请联系我们

精彩绝伦的CSS

精彩绝伦的CSS

[美] Eric A. Meyer / 姬光 / 人民邮电出版社 / 2012-7 / 49.00元

内容简介: 打造现代布局的专业技术 本书远非只是介绍基础知识,它不仅全面细致地讲解布局与效果,而且展望了HTML5和CSS3的未来。业内很少有人能像Eric A. Meyer一样详细阐明CSS,他在本书中深入分析了普遍适用的实用技术,讲解了如何选用正确的工具、如何通过jQuery使用CSS效果和CSS3技术。 本书主要内容如下: 显示或隐藏元素 通过XHTML为bod......一起来看看 《精彩绝伦的CSS》 这本书的介绍吧!

CSS 压缩/解压工具
CSS 压缩/解压工具

在线压缩/解压 CSS 代码

URL 编码/解码
URL 编码/解码

URL 编码/解码

RGB HSV 转换
RGB HSV 转换

RGB HSV 互转工具