实战-单例模式和创建生产者相结合

实际中遇到了这样一个问题:
The producer group[xxxx] has been created before, specify another instanceName (like producer.setInstanceName) please.

发生的原因是:一个进程内 ,创建了多个相同topic的producer。

所以问题就转换成了如何避免进程内多个实例的创建。(还有一个解决办法就是producer.setInstanceName(UUID.getUUID()))

解决问题:就要用到了单例模式。

单例模式可以参考:synchronized能不能保证有序性??单例模式下的懒汉和双检锁的思考


分析:

为啥不用分布式锁呢?分布式其实保证集群内唯一,就是不管你有多少台机器,全局就一个,唯一的一个。

分布式环境,其实就是不同的进程间的问题。集群内唯一,实质就是进程间唯一

"进程唯一"指的是进程内唯一、进程间不唯一。"线程唯一"指的是线程内唯一、线程间不唯一。集群相当于多个进程构成的一个集合,"集群唯一"就相当于是进程内唯一、进程间也唯一。也就是说,不同的进程间共享同一个对象,不能创建同一个类的多个对象。

我们知道,经典的单例模式是进程内唯一的,那如何实现一个进程间也唯一的单例呢?如果严格按照不同的进程间共享同一个对象来实现,那集群唯一的单例实现起来就有点难度了。

具体来说,我们需要把这个单例对象序列化并存储到外部共享存储区(比如文件)。进程在使用这个单例对象的时候,需要先从外部共享存储区中将它读取到内存,并反序列化成对象,然后再使用,使用完成之后还需要再存储回外部共享存储区。

为了保证任何时刻,在进程间都只有一份对象存在,一个进程在获取到对象之后,需要对对象加锁,避免其他进程再将其获取。在进程使用完这个对象之后,还需要显式地将对象从内存中删除,并且释放对对象的加锁。


1.如何理解单例模式的唯一性?

单例类中对象的唯一性的作用范围是"进程唯一"的。"进程唯一"指的是进程内唯一,进程间不唯一;"线程唯一"指的是线程内唯一,线程间可以不唯一。实际上,"进程唯一"就意味着线程内、线程间都唯一,这也是"进程唯一"和"线程唯一"的区别之处。"集群唯一"指的是进程内唯一、进程间也唯一。

2.如何实现线程唯一的单例?

我们通过一个HashMap来存储对象,其中key是线程ID,value是对象。这样我们就可以做到,不同的线程对应不同的对象,同一个线程只能对应一个对象。实际上,Java语言本身提供了ThreadLocal并发工具类,可以更加轻松地实现线程唯一单例。

3.如何实现集群环境下的单例?

我们需要把这个单例对象序列化并存储到外部共享存储区(比如文件)。进程在使用这个单例对象的时候,需要先从外部共享存储区中将它读取到内存,并反序列化成对象,然后再使用,使用完成之后还需要再存储回外部共享存储区。为了保证任何时刻在进程间都只有一份对象存在,一个进程在获取到对象之后,需要对对象加锁,避免其他进程再将其获取。在进程使用完这个对象之后,需要显式地将对象从内存中删除,并且释放对对象的加锁。

4.如何实现一个多例模式?

"单例"指的是一个类只能创建一个对象。对应地,"多例"指的就是一个类可以创建多个对象,但是个数是有限制的,比如只能创建3个对象。多例的实现也比较简单,通过一个Map来存储对象类型和对象之间的对应关系,来控制对象的个数。

参考

1.https://blog.51cto.com/u_15273875/2917903

2.王铮《设计模式之美》

相关推荐
乙己40712 小时前
设计模式——单例模式(singleton)
java·c++·单例模式·设计模式
空空kkk1 天前
单例模式详解
单例模式
shaominjin1232 天前
单例模式:设计模式中的“独一无二“之道
android·单例模式·设计模式
北邮-吴怀玉4 天前
6.3.3.1 大数据方法论与实践指南-大数据质量度量指标体系
大数据·单例模式
报错小能手5 天前
C++笔记(面向对象)详解单例模式
c++·笔记·单例模式
闲人编程9 天前
Python设计模式实战:用Pythonic的方式实现单例、工厂模式
开发语言·python·单例模式·设计模式·工厂模式·codecapsule·pythonic
W.Buffer9 天前
设计模式-单例模式:从原理到实战的三种经典实现
开发语言·javascript·单例模式
pcm12356710 天前
java中的单例模式
java·开发语言·单例模式
czy878747511 天前
用C语言实现单例模式
c语言·单例模式
杯莫停丶12 天前
设计模式之:单例模式
java·单例模式·设计模式