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

实际中遇到了这样一个问题:
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.王铮《设计模式之美》

相关推荐
极光雨雨1 小时前
【设计模式】单例模式 饿汉式单例与懒汉式单例
单例模式·设计模式
贱贱的剑5 小时前
2.单例模式
单例模式·设计模式
有没有没有重复的名字3 天前
线程安全的单例模式与读者写者问题
java·开发语言·单例模式
小李飞飞砖3 天前
kotlin
开发语言·单例模式·kotlin
想躺平的咸鱼干6 天前
Volatile解决指令重排和单例模式
java·开发语言·单例模式·线程·并发编程
鼠鼠我呀27 天前
【设计模式04】单例模式
单例模式·设计模式
花好月圆春祺夏安7 天前
基于odoo17的设计模式详解---单例模式
单例模式·设计模式
布兰妮甜8 天前
单例模式在前端(JavaScript)中的实现与应用
前端·javascript·单例模式
N_NAN_N9 天前
类图+案例+代码详解:软件设计模式----单例模式
java·单例模式·设计模式
X_StarX9 天前
【Unity笔记01】基于单例模式的简单UI框架
笔记·ui·unity·单例模式·游戏引擎·游戏开发·大学生