单例设计模式(3)

news2024/11/24 4:25:20

单例模式(3)

实现集群环境下的分布式单例类

如何理解单例模式中的唯一性?
  • 单例模式创建的对象是进程唯一的。以springboot应用程序为例,他是一个进程,可能包含多个线程,单例代表在这个进程的某个类是唯一的,在不同的线程中类是相同的。
如何实现线程唯一的单例?
/**
 * 线程中的单例
 */
public class ThreadIdGenrator {
    private static final Map<Long, ThreadIdGenrator> map = new ConcurrentHashMap<>();

    private AtomicInteger id = new AtomicInteger(0);


    public static ThreadIdGenrator getInstance() {
        long threadId = Thread.currentThread().getId();
        ThreadIdGenrator threadIdGenrator = map.putIfAbsent(threadId, new ThreadIdGenrator());
        return threadIdGenrator;
    }

    public int nextInt() {
        return id.incrementAndGet();
    }
}
如何实现集群环境下的单例?
  • 我们需要把这个单例对象序列化并存储到外部共享存储区(比如文件)。进程在使用这个单例对象的时候,需要先从外部共享存储区中将它读取到内存,并反序列化成对象,然后再使用,使用完成之后还需要再存储回外部共享存储区。

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

  • 问题:这里为什么要加锁

    • 理由:如果多个进程读取同一份序列化文件,得到的对象的地址是不一样的,这样子就无法保证全局的唯一性;
    • 序列化后的对象与原对象只是值相等但是对象的地址是不相等
    • 为了保证全局的唯一性,必须保证在集群下,在使用单例对象时,需要加锁,当多线程使用时,只有一个线程可以使用成功,其他线程必须阻塞
import java.util.concurrent.atomic.AtomicLong;

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 static IdGenerator getInstance() {
        if (instance == null) {
            lock.lock();
            instance = storage.load(IdGenerator.class);
            lock.unlock(); // 放置于try-finally块内确保解锁
        }
        return instance;
    }

    public void freeInstance() {
        lock.lock();
        try {
            storage.save(this, IdGenerator.class);
            instance = null; // 释放对象
        } finally {
            lock.unlock();
        }
    }

    public long getId() {
        return id.incrementAndGet();
    }
}

如何实现一个多例模式?
  • 多例的理解
    • “多例”指的就是,一个类可以创建多个对象,但是个数是有限制的
    • 同一类型的只能创建一个对象,不同类型的可以创建多个对象
      • 类型:同一个 name 获取到的对象实例是相同的
      • 以ID生成器为例:我希望在用户注册时使用的是一个ID生成器;在增加商品时,使用的是另一个ID生成器,即根据场景划分使用不同的ID生成器
public class DuoLiIdGenertor {
    private static final Map<String, DuoLiIdGenertor> map = new ConcurrentHashMap<>();

    private AtomicInteger id = new AtomicInteger(0);

    public static DuoLiIdGenertor getInstance(String name) {
        map.putIfAbsent(name, new DuoLiIdGenertor());
        return map.get(name);
    }


    public int nextInt() {
        return id.incrementAndGet();
    }
 }
  public static void main(String[] args) {
        DuoLiIdGenertor user = getInstance("user");
        DuoLiIdGenertor goods = getInstance("goods");
        DuoLiIdGenertor user1 = getInstance("user");

        System.out.println(user.hashCode());
        System.out.println(goods.hashCode());
        System.out.println(user1.hashCode());

    }   

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1558098.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

跨境电商IP防关联是什么?有什么作用?

做跨境电商的朋友应该都知道IP防关联这个词,那么为何IP需要防关联呢&#xff1f;今天为大家来解答这个问题。 跨境电商IP防关联是指在跨境电商运营中&#xff0c;通过采取一系列技术手段&#xff0c;确保每个跨境电商账号使用独立的IP地址&#xff0c;以避免账号之间因为IP地址…

【Linux实践室】Linux用户管理实战指南:用户权限切换操作详解

&#x1f308;个人主页&#xff1a;聆风吟_ &#x1f525;系列专栏&#xff1a;Linux实践室、网络奇遇记 &#x1f516;少年有梦不应止于心动&#xff0c;更要付诸行动。 文章目录 一. ⛳️任务描述二. ⛳️相关知识2.1 &#x1f514;图形化界面登录2.2 &#x1f514;使用login…

【java苍穹外卖项目实战四】新增员工功能

文章目录 1、需求设计分析2、接口设计3、表设计4、设计DTO类5、Controller层功能实现6、Service层功能实现7、Mapper层功能实现 1、需求设计分析 一般在做需求分析时&#xff0c;往往都是对照着产品原型进行分析&#xff0c;因为产品原型比较直观&#xff0c;便于我们理解业务…

Unreal的Quixel Bridge下载速度过慢、下载失败

从Quixel Bridge下载MetaHuman模型&#xff0c;速度非常慢&#xff0c;而且经常下载失败&#xff0c;从头下载。 可以从Quixel Bridge的右上角我的图标->Support->Show Logs打开日志目录 downloaded-assets目录下为下载的资源 bridge-plugin.log文件记录了下载URL和下载…

矩阵间关系的建立

参考文献 2-D Compressive Sensing-Based Visually Secure Multilevel Image Encryption Scheme 加密整体流程如下: 我们关注左上角这一部分: 如何在两个图像之间构建关系,当然是借助第3个矩阵。 A. Establish Relationships Between Different Images 简单说明如下: …

leetcode 331. 验证二叉树的前序序列化【计数器】

原题链接&#xff1a;331. 验证二叉树的前序序列化 题目描述&#xff1a; 序列化二叉树的一种方法是使用 前序遍历 。当我们遇到一个非空节点时&#xff0c;我们可以记录下这个节点的值。如果它是一个空节点&#xff0c;我们可以使用一个标记值记录&#xff0c;例如 #。 例如…

鸿蒙OS开发实例:【瀑布流式图片浏览】

介绍 瀑布流式展示图片文字&#xff0c;在当前产品设计中已非常常见&#xff0c;本篇将介绍关于WaterFlow的图片浏览场景&#xff0c;顺便集成Video控件&#xff0c;以提高实践的趣味性 准备 请参照[官方指导]&#xff0c;创建一个Demo工程&#xff0c;选择Stage模型熟读Har…

思维题,LeetCode331. 验证二叉树的前序序列化

一、题目 1、题目描述 序列化二叉树的一种方法是使用 前序遍历 。当我们遇到一个非空节点时&#xff0c;我们可以记录下这个节点的值。如果它是一个空节点&#xff0c;我们可以使用一个标记值记录&#xff0c;例如 #。 例如&#xff0c;上面的二叉树可以被序列化为字符串 &quo…

数字孪生|山海鲸可视化软件Windows版安装步骤

哈喽&#xff0c;大家好啊&#xff0c;我是雷工&#xff01; 今天尝试下该数字孪生软件&#xff0c;以下为安装步骤&#xff0c;我这里安装的是Windows版本。 1、系统配置要求 由于该软件主要功能是为了编辑可视化大屏&#xff0c;因此该软件必须安装在有桌面的系统内。 2、…

动态规划详细讲解c++|经典例题讲解认识动态规划|0-1背包问题详解

引言 uu们&#xff0c;你们好&#xff01;这次的分享是动态规划&#xff0c;其中介绍了动态规划的相关概念和做题模板&#xff08;三要素&#xff09;&#xff0c;同时为了uu们对动态规划方法有更加形象的认识&#xff0c;特地找了两个经典问题&#xff0c;和大家一起分析。并…

关于未来自我的发展和一些学习方法(嵌入式方向)

我是一名大二的学生&#xff0c;考研还是就业&#xff0c;到底是重视专业课还是重视数学英语&#xff0c;这些问题一直困扰了我很久&#xff0c;但如今已经有了一些浅显的认识&#xff0c;所以才会想写这样一篇文章来记录一下自己的状态和未来的规划 下面的看法都是个人的看法&…

WMware虚拟机配置静态IP

注意&#xff1a;如果是克隆的虚拟机&#xff0c;需要先重新生成mac地址&#xff0c;如下图所示 修改配置文件 &#xff1a;/etc/sysconfig/network-scripts/ifcfg-ens33 注意&#xff1a;1. BOOTPROTO设置为static 2.将下面的IPADDR地址替换为你实际要设置的ip地址 3.NAT模式…

Unity urp渲染管线下,动态修改材质球surfaceType

在项目中遇到了需要代码动态修改材质球的surfaceType&#xff0c;使其动态切换是否透明的需求。 urp渲染管线下&#xff0c;动态修改材质球的surfaceType&#xff0c;查了大部分帖子&#xff0c;都有一些瑕疵&#xff0c;可能会造成透明后阴影投射有问题。 其次在webgl平台上…

postcss安装和使用(详细)

1,安装postcss&#xff1a; 在此之前需要安装有node.js 第一步 命令&#xff1a;cnpm install postcss-cli -g 第二步 命令&#xff1a;cnpm install postcss –g 推荐内容 2,下载autoprefixer插件&#xff0c;并创建postcss.config.js文件并写入配置代码 autoprefixer插件…

Node.js中Router的使用

文章目录 介绍router的优点1.导入Express和创建Router&#xff1a;2. 定义路由&#xff1a;3.将router暴露到模块外&#xff1a;4. 将Router挂载到Express应用中&#xff1a;4.1.引入router4.2.使用中间件让router在Express应用中生效(三种写法) 5. 完整示例&#xff1a;5.1.编…

【Canvas与艺术】三斜齿齿轮联动效果展示

【关键点】 1.斜齿齿轮的具体画法&#xff1b; 2.相邻两齿轮的啮合角是多少。 【图示】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head>&…

【Docker】搭建强大易用的个人博客 - Halo

【Docker】搭建强大易用的个人博客 - Halo 前言 本教程基于绿联的NAS设备DX4600 Pro的docker功能进行搭建&#xff0c;采用Halo MySQL实例作为演示。 简介 Halo [ˈheɪloʊ] 是一个简洁&#xff0c;现代&#xff0c;快速且非常灵活的建站工具&#xff0c;它是由一位中国开…

HTML常用的图片标签和超链接标签

目录 一.常用的图片标签和超链接标签&#xff1a; 1.超链接标签&#xff1a; 前言: 超链接的使用&#xff1a; target属性: 1)鼠标样式&#xff1a; 2)颜色及下划线: 总结: 2.图片标签&#xff1a; 前言: img的使用: 设置图片&#xff1a; 1.设置宽度和高度: 2.HTM…

改进的图像LSB加密算法:Matrix encoding embedding

参考文献1 Visually secure image encryption using adaptive-thresholding sparsification and parallel compressive sensing 算法实现 简单说明 算法步骤概述 定义函数f:这个函数用于计算给定码字b的一个特定值,此值将与秘密信息x进行比较。这个计算涉及到将码字b的每一…

突发: xz-utils 被注入后门 (CVE-2024-3094)

Andres Freund 在 2024 年 3 月 29 日发现了一个在 xz-utils 注入的后门&#xff1b;使用了 xz/lzma 5.6.0 / 5.6.1 的项目皆受影响。 杀伤力: 当前还未完全清楚&#xff1b;但 openssh 的 sshd 首当其冲&#xff1b;注入的代码会 Hook OpenSSH 的 RSA_public_decrypt 函数&a…