设计模式(五):单件模式(单例模式)

设计模式(五):单件模式(单例模式)文章目录一 单件模式 定义二 使用 2 1 饿汉式 2 2 懒汉式 2 3 小细节三 单件模式的多线程安全问题 3 1 懒汉式分析一 3 2 懒汉式分析二 3 3 懒汉式分析三参考一 单件模式 定义确保一个类只有一个实例 并提供一个全局

大家好,欢迎来到IT知识分享网。

一、『单件模式』定义

确保一个类只有一个实例,并提供一个全局访问点。

单件模式即单例模式。

使用场景很多,比如多个程序都要使用一个配置文件中的数据,而且要实现数据共享和交换。必须要将多个数据封装到一个对象中,而且多个程序操作的是同一个对象,也就是说必须保证这个配置文件对象的唯一性。

有两种方式实现:饿汉式和懒汉式。

二、使用

2.1 饿汉式

单件模式的急切实例化方式,上来就创建对象:

class Single { 
    //2,创建一个本类对象。 private static Single uniqueInstance = new Single(); //1,私有化构造函数。禁止程序创建该类的对象。 private Single() { 
    } //3,定义一个方法返回这个对象。该方法加上public,权限最大。 public static Single getInstance() { 
    return uniqueInstance; } } / * 演示 */ public class Demo { 
    public static void main(String[] args) { 
    // 调用getInstance方法获取Single的对象。 Single ss1 = Single.getInstance(); Single ss2 = Single.getInstance(); // ss1和ss2操作的是同个对象,因为地址相同 System.out.println(ss1 == ss2); } } 

如果创建的这个单件对象一直没用到过,而且该对象也一直比较占用空间,那么饿汉式并不是很完美的解决方法。

2.2 懒汉式

单例的延迟实例化方式,用到才创建对象:

class Single { 
    //2,创建一个本类对象。 private static Single uniqueInstance = null; //1,私有化构造函数。禁止程序创建该类的对象。 private Single() { 
    } //3,定义一个方法返回这个对象。该方法是关键,加上public,权限最大。 public static Single getInstance() { 
    if (uniqueInstance == null) uniqueInstance = new Single(); return uniqueInstance; } } / * 演示 */ public class Demo { 
    public static void main(String[] args) { 
    // 调用getInstance方法获取Single的对象。 Single ss1 = Single.getInstance(); Single ss2 = Single.getInstance(); // ss1和ss2操作的是同个对象,因为地址相同 System.out.println(ss1 == ss2); } } 

2.3 小细节

(1)私有化构造函数是为了禁止其它程序创建该类的对象,保证只有该类内部才能创建该类的对象。

(2)想获取Single类的对象就需要调用getInstance方法。既然无法通过对象调用,那么只能用类名调用,所以getInstance方法必须是static。

(3)创建好对象后,因为uniqueInstance对象是静态的,所以通过Single.uniqueInstance这种方式是可以获取对象的,但不推荐,用方法访问是为了对对象可控,因此对象需加上private。

三、单件模式的多线程安全问题

对比饿汉式和懒汉式两种单件模式的实现,饿汉式没有多线程安全问题,但是懒汉式是有多线程安全问题的。

3.1 懒汉式分析一

初始的饿汉式实现:

class Single { 
    //2,创建一个本类对象。 private static Single uniqueInstance = null; //1,私有化构造函数。禁止程序创建该类的对象。 private Single() { 
    } //3,定义一个方法返回这个对象。该方法是关键,加上public,权限最大。 public static Single getInstance() { 
    if (uniqueInstance == null) uniqueInstance = new Single(); return uniqueInstance; } } 

问题:假设现在uniqueInstance对象还是null,然后有多个线程同时调用getInstance()方法想获得uniqueInstance对象,可能会出现多个线程都判断uniqueInstance为空,接着就重复new了对象,这里就出现多线程安全问题了。

3.2 懒汉式分析二

上面分析发现:并发访问会有安全隐患,所以加入同步机制解决安全问题。

class Single { 
    //2,创建一个本类对象。 private static Single uniqueInstance = null; //1,私有化构造函数。禁止程序创建该类的对象。 private Single() { 
    } //3,定义一个方法返回这个对象。该方法是关键,加上public,权限最大。 public static Single getInstance() { 
    synchronized (Single.class) { 
    if (uniqueInstance == null) uniqueInstance = new Single(); } return uniqueInstance; } } 

问题:只有第一次执行此方法时,才真正需要同步。换句话说,一旦创建好uniqueInstance对象,就不再需要同步这个方法了。之后每次调用这个方法,同步都是一种累赘。

3.3 懒汉式分析三

上面分析发现:同步的出现降低了效率。可以通过双重判断的方式,解决效率问题,减少判断锁的次数。

class Single { 
    //2,创建一个本类对象。 private volatile static Single uniqueInstance = null; //1,私有化构造函数。禁止程序创建该类的对象。 private Single() { 
    } //3,定义一个方法返回这个对象。该方法是关键,加上public,权限最大。 public static Single getInstance() { 
    if(uniqueInstance == null) { 
    synchronized (Single.class) { 
    if (uniqueInstance == null) uniqueInstance = new Single(); } } return uniqueInstance; } } 

volatile关键词确保:uniqueInstance变量被初始化成Single实例时,多个线程正确地处理uniqueInstance变量。

参考

《HeadFirst设计模式》

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/141949.html

(0)
上一篇 2025-05-13 19:26
下一篇 2025-05-13 19:45

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信