39、单例模式(下)
1、单例的唯一性
单例类在老进程中存在且只能存在一个对象,在新进程中也会存在且只能存在一个对象,而且这两个对象并不是同一个对象
这也就说:单例类中对象的唯一性的作用范围是进程内的,在进程间是不唯一的
2、线程唯一单例
public class IdGeneratorThread { private IdGeneratorThread() { } private static final ConcurrentHashMap<Long, IdGeneratorThread> INSTANCES = new ConcurrentHashMap<>(); public static IdGeneratorThread getInstance() { long currentThreadId = Thread.currentThread().getId(); INSTANCES.putIfAbsent(currentThreadId, new IdGeneratorThread()); return INSTANCES.get(currentThreadId); } private final AtomicLong id = new AtomicLong(0); public long getId() { return id.incrementAndGet(); } }
3、集群环境下的单例
我们需要把这个单例对象序列化并存储到外部共享存储区(比如文件)
进程在使用这个单例对象的时候,需要先从外部共享存储区中将它读取到内存,并反序列化成对象,然后再使用,使用完成之后还需要再存储回外部共享存储区
为了保证任何时刻在进程间都只有一份对象存在,一个进程在获取到对象之后需要对对象加锁,避免其他进程再将其获取
在进程使用完这个对象之后,还需要显式地将对象从内存中删除,并且释放对对象的加锁
public class IdGenerator { private AtomicLong id = new AtomicLong(0); private static IdGenerator instance; private static SharedObjectStorage storage = FileSharedObjectStorage(/*入参省略, 比如文件地址*/); private static DistributedLock lock = new DistributedLock(); // 分布式锁 private IdGenerator() { } public synchronized static IdGenerator getInstance() { if (instance == null) { lock.lock(); instance = storage.load(IdGenerator.class); } return instance; } public synchronized void freeInstance() { storage.save(this, IdGeneator.class); instance = null; // 释放对象 lock.unlock(); } public long getId() { return id.incrementAndGet(); } }
4、多例
// 后端服务器 public class BackendServer { private long serverNo; private String serverAddr; private static final int SERVER_COUNT = 3; private static final Map<Long, BackendServer> serverInstances = new HashMap<>(); static { serverInstances.put(1L, new BackendServer(1L, "192.168.135:8080")); serverInstances.put(2L, new BackendServer(2L, "192.168.136:8081")); serverInstances.put(3L, new BackendServer(3L, "192.168.137:8082")); } private BackendServer(long serverNo, String serverAddr) { this.serverNo = serverNo; this.serverAddr = serverAddr; } public BackendServer getInstance(long serverNo) { return serverInstances.get(serverNo); } private static final Random RANDOM = new Random(); public BackendServer getRandomInstance() { return serverInstances.get((long) RANDOM.nextInt(SERVER_COUNT) + 1); } }
本文来自博客园,作者:lidongdongdong~,转载请注明原文链接:https://www.cnblogs.com/lidong422339/p/17505734.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步