JAVA设计模式-单例模式

JAVA设计模式-单例模式

单例模式

类只能有一个实例,在内存中会创建并且只创建一次对象。所有其他类或者其他需要调用的地方都是用这一个对象,可以防止频繁创建对象,内存占用高。特点:只能有一个实例,并且能够自行创建这个实例的类。

实现

饿汉模式

写法一
介绍

在类的加载时就已经创建好对象,线程是安全的,但是会浪费资源。参考源码:JDK1.8 com.sun.glass.ui.monocle.KeyInput类

JAVA设计模式-单例模式
代码示例
public class Singleton {
    /**
     * 私有的构造方法,可以防止外部调用时new进行创建对象
     */
    private Singleton(){};
    /**
     * 创建私有的对象
     */
    private static Singleton singleton = new Singleton();

    /**
     * 提供公共的对外的获取方法
     * @return
     */
    public static Singleton getInstance(){
        return singleton;
    }
}
写法二
介绍

在类的加载时就已经创建好对象,此处是使用静态代码块进行创建,线程是安全的。

JAVA设计模式-单例模式
代码示例
public class Singleton {

    /**
     * 私有的构造方法,可以防止外部调用时new进行创建对象
     */
    private Singleton(){};
    /**
     * 创建私有的对象
     */
    private static Singleton singleton = null;

    static {
        singleton = new Singleton();
    }

    /**
     * 提供公共的对外的获取方法
     * @return
     */
    public static Singleton getInstance(){
        return singleton;
    }
}

懒汉模式

写法一
介绍

在第一次使用时进行创建对象,如果多个线程同时调用了getInstance()方法,可能会创建多个对象,线程是不安全的。

JAVA设计模式-单例模式
代码示例
public class Singleton {

    /**
     * 私有的构造方法,可以防止外部调用时new进行创建对象
     */
    private Singleton(){};
    /**
     * 创建私有的对象,注意此处不进行new创建
     */
    private static Singleton singleton;

    /**
     * 提供公共的对外的获取方法
     * @return
     */
    public static Singleton getInstance(){
        // 多个线程同时执行这边时,可能会创建多个对象
        if(singleton == null){
            singleton = new Singleton();
        }
        return singleton;
    }
}
写法二
介绍

这种写法也是在第一次调用时进行创建对象,但是在该方法上增加了synchronized同步锁,这样就可以保证只会有一个线程执行。线程是安全的,但是synchronized在1.6之前性能比较差,1.6之后进行了优化,性能提升,但是此处为了保证线程安全,使用synchronized,还是多少会影响性能。

JAVA设计模式-单例模式
代码示例
public class Singleton {

    /**
     * 私有的构造方法,可以防止外部调用时new进行创建对象
     */
    private Singleton(){};
    /**
     * 创建私有的对象,注意此处不进行new创建
     */
    private static Singleton singleton;

    /**
     * 提供公共的对外的获取方法
     * @return
     */
    public static synchronized Singleton getInstance(){
        // 第一次调用时进行创建对象
        if(singleton == null){
            singleton = new Singleton();
        }
        return singleton;
    }
}
写法三
介绍

这种写法采用双重锁的方式,进行判断并创建对象。线程是不安全的。

JAVA设计模式-单例模式

分析线程不安全原因:首先在内存中创建对象,需要进行
①分配内存地址
②初始化对象
③设置对象指向刚刚分配的内存地址
但是在编译器、指令集并行、内存中都可能进行指令重排序。如果发生指令重排序,对于单线程来说,如果执行①③②和执行①②③的结果是一样的,但是如果是多线程,在线程A执行完①③之后,如果线程B进入到第一个if语句,则会判断singleton已经指向一个地址,不等于null,则直接返回,此时返回的对象是还未进行初始化的空对象。

代码示例
public class Singleton {

    /**
     * 私有的构造方法,可以防止外部调用时new进行创建对象
     */
    private Singleton(){};
    /**
     * 创建私有的对象,注意此处不进行new创建
     */
    private static Singleton singleton;

    /**
     * 提供公共的对外的获取方法
     * @return
     */
    public static Singleton getInstance(){
        if(singleton == null){
            synchronized (Singleton.class){
                if(singleton == null){
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}
写法四
介绍

在写法三的基础上,增加volatile,volatile可以禁止指令重排序并且保证共享变量不同线程之间的可见性。

JAVA设计模式-单例模式
代码示例
public class Singleton {

    /**
     * 私有的构造方法,可以防止外部调用时new进行创建对象
     */
    private Singleton(){};
    /**
     * 创建私有的对象,注意此处不进行new创建, 使用volatile
     */
    private volatile static Singleton singleton;

    /**
     * 提供公共的对外的获取方法
     * @return
     */
    public static Singleton getInstance(){
        if(singleton == null){
            synchronized (Singleton.class){
                if(singleton == null){
                    singleton = new Singleton();
                }
            }
        }
        return singleton;
    }
}

原文链接:https://monkey.blog.xpyvip.top/archives/java-she-ji-mo-shi—dan-li-mo-shi

Original: https://www.cnblogs.com/aibianchengya/p/16703677.html
Author: 程序猿的代码
Title: JAVA设计模式-单例模式

原创文章受到原创版权保护。转载请注明出处:https://www.johngo689.com/577830/

转载文章受原作者版权保护。转载请注明原作者出处!

(0)

大家都在看

  • Shell脚本监控线上端口服务是否正常开启

    前言: 线上服务正常可用是至关重要的,当正在运行的某个端口服务异常停止,我们期望定时脚本可以自动启动,而无需遇到问题再人为的启动。 例如:监听Mysql服务是否正常,我们通常的思路…

    Linux 2023年5月28日
    0100
  • 小程序字节转GBK及UTF8

    前段时间在Android原生搞的BLE扫码枪又要移植到小程序上来。本以为小程序不支持BLE的,结果一搜,还真支持-_-|| 。 蓝牙部分问题不大,遇到的主要问题是, 小程序环境如何…

    Linux 2023年6月13日
    0186
  • 爬虫

    简介: 浏览器发送http请求,去后端服务器获取到数据之后只能从浏览器中看,如果要把需要的数据保存到本地,存到我们自己库中就可以用到爬虫 百度本质就是一个大爬虫(搜索),在输入框中…

    Linux 2023年6月14日
    0100
  • 如何在 pyqt 中捕获并处理 Alt+F4 快捷键

    前言 如果在 Windows 系统的任意一个窗口中按下 Alt + F4,默认行为是关闭窗口(或者最小化到托盘)。对于使用了亚克力效果的窗口,使用 Alt + F4 最小化到托盘,…

    Linux 2023年6月7日
    0116
  • locate-updatedb命令检索不全

    执行updatedb 命令,用于立刻更新locate 命令所必需的数据库文件,但有些文件可能会在检索过程中被过滤掉。 有时候明明存在的文件,用find 命令都能搜得出来,但用loc…

    Linux 2023年6月13日
    088
  • MySQL实现备份(3)之xtrabackup 备份工具

    xtrabackup工具: 是percona公司开发的一个用于对MySQL进行备份的工具。相对于mysqldump,xtrabackup支持增量备份、差异备份等。 使用手册;htt…

    Linux 2023年6月7日
    0126
  • 博客园排名预测

    前言 之前写过一篇绘制博客园积分与排名趋势图的文章——《查看博客园积分与排名趋势图的工具》,使用那篇文章介绍的工具,可以通过趋势图直观的看出排名前进的走势。但是如果想看看自己积分达…

    Linux 2023年6月6日
    097
  • Linux 系统IO响应缓慢系统hang住

    应急处理:reboot 解决方法: sysctl -w vm.dirty_ratio=10 sysctl -w vm.dirty_background_ratio=5 sysctl…

    Linux 2023年6月13日
    096
  • 搭建Nginx(haproxy)+keepalived+Tomcat双主高可用负载均衡

    周末的时候一个正在学Linux的朋友问我,高可用怎么玩?我和他微信了将近三个小时,把Nginx和haproxy双主高可用教给他了,今天突然想把这个给写进博客里,供给那些正在学习Li…

    Linux 2023年6月8日
    067
  • 投票活动进行中!探讨问题:从互联网大量收集学习资料再包装成产品售卖盈利是否属于侵权违法?

    写在开篇 今天不聊某项技能的知识点,我们聊点别的。那么,到底聊啥好呢?笔者想想… 有了,这两天笔者从一个微信公众号中发现一个非常恶劣的营销行为。事情大概背景是这样的:运…

    Linux 2023年6月7日
    077
  • 搭建mount+nfs远程挂载

    需求背景: 192.168.10.100 源服务器 目录:/root/test 目录属主属组普通用户,权限777 192.168.10.111 目标服务器 目录:/root/tes…

    Linux 2023年6月8日
    0104
  • CentOS 7.6 安装 MySQL-5.7.31(RPM方式安装)

    准备工作: 注:5.7.31版本安装步骤及初始化和之前版本有较大区别 CentOS 7.6 系统: 带GUI的服务器 默认安装 MySQL 5.7.31 安装包: 1.RPM安装包…

    Linux 2023年6月8日
    085
  • 每日好书推荐:《Kali Linux渗透测试的艺术》PDF高清版

    Original: https://www.cnblogs.com/bnn86/p/15344056.htmlAuthor: 测试楠楠君Title: 每日好书推荐:《Kali Li…

    Linux 2023年5月27日
    0108
  • Android BLE 蓝牙开发——扫码枪基于BLESSED

    一、蓝牙模式HID与BLE 当扫码枪与手机连接时,通常采用的是 蓝牙HID(Human Interface Device)模式。本质上是一个把扫码枪作为一个硬件键盘,按照键盘协议把…

    Linux 2023年6月13日
    0105
  • Python 装饰器

    直接进入主题 原代码 以下是原代码,要求给改代码添加统计时间功能 版本1(直接在原函数上修改) 可能有的同学就做出了下面这个版本 版本2(将函数当做参数传入) 经过修改上面的版本我…

    Linux 2023年6月13日
    0100
  • 了解Redis这个核心数据类型

    string 字符串 tring 类型是二进制安全的,即 string 中可以包含任何数据。 Redis 中的普通 string 采用 raw encoding …

    Linux 2023年5月28日
    095
亲爱的 Coder【最近整理,可免费获取】👉 最新必读书单  | 👏 面试题下载  | 🌎 免费的AI知识星球