设计模式学习05----之单例模式

举报
码农飞哥 发表于 2021/05/29 13:16:02 2021/05/29
【摘要】 单例模式,是我们最常用也最熟悉的一种设计模式,其使用要注意线程安全。 定义 单例模式:顾名思义,就是在应用中有且只有一个实例。一般类似于计数器类的都必须是单例,多例会导致计数结果不准。 一般而言,其分为饿汉式和懒汉式。 懒汉式 懒汉式:顾名思义,就是不在系统加载时创建类的实例。而是在调用时才去一次性创建。 demo如下: package com.singlet...

单例模式,是我们最常用也最熟悉的一种设计模式,其使用要注意线程安全。

定义

单例模式:顾名思义,就是在应用中有且只有一个实例。一般类似于计数器类的都必须是单例,多例会导致计数结果不准。
一般而言,其分为饿汉式和懒汉式。

懒汉式

懒汉式:顾名思义,就是不在系统加载时创建类的实例。而是在调用时才去一次性创建。
demo如下:

package com.singleton;

/**
 * 懒汉式
 * @author xiang.wei
 */
public class LazySingleton {
	/**
	 * 定义一个私有变量,目的是外部不能直接访问该变量,必须通过公共的访问方法来访问
	 */
	private static LazySingleton instance=null;

	/**
	 * 私有化构造器,使之不能直接构造对象
	 */
	private LazySingleton(){ }

	/**
	 * 公共的提取对象的方法
	 * @return
	 */
	public synchronized static LazySingleton getInstance() { if (instance==null) { instance=new LazySingleton(); } return instance;
	}
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31

饿汉式

饿汉式:与懒汉式相反,饿汉式就是在系统加载时就去创建类的实例。
demo如下:

package com.singleton;

/**
 * 饿汉式
 * @author xiang.wei
 * @create 2018/4/10 10:34
 */
public class HungrySingleton { private static final HungrySingleton SINGLETON = new HungrySingleton(); private HungrySingleton() { } public static HungrySingleton getInstance() { return SINGLETON; }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18

总结:饿汉式与懒汉式相比要占用更多的内存,因为系统加载之后就会创建实例。但是效率要比懒汉式要高。

双重加锁

双重加锁是懒汉式的一种扩展。因为直接在getInstance()上加上synchronized会导致每次调用方法时都需要加锁。执行效率不高。所以,我们采用了双重加锁的方式。

package com.singleton;

/**
 * 懒汉式
 * 双重加锁
 * @author xiang.wei
 */
public class LazySingleton_two { /** * 定义一个私有变量,目的是外部不能直接访问该变量,必须通过公共的访问方法来访问 */ private static  volatile LazySingleton_two instance = null; /** * 私有化构造器,使之不能直接构造对象 */ private LazySingleton_two() { } /** * 公共的提取对象的方法 * * @return */ public static LazySingleton_two getInstance() { //如果单例存在则直接返回 if (instance == null) { //单例不存在,则进入同步代码块 synchronized (LazySingleton_two.class) { if (instance == null) { System.out.println("实例化的次数"); instance = new LazySingleton_two(); } } } return instance; }
}


  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40

双重加锁并不是加两个synchronized关键字。
第一个判断是当对象存在时则直接返回实例,当对象不存在时则进入同步代码块中,同步代码块的作用跟之前是相同的,就是防止两个线程同时访问同步代码块的内容,造成生成多个实例的情况。同步代码块每次只允许一个线程进入,创建完实例后返回。第二个判断是当多个线程排队进入代码块时,第一个线程创建完实例返回后,第二个线程再进入时,不需要在创建实例。
采用双重加锁后,代码的执行效率有了较大的提升。

静态内部类的方式

public class MySingleton { private static class MySingletonHandle { private static final MySingleton instance = new MySingleton(); } private MySingleton() { } public MySingleton getSingleton() { return MySingletonHandle.instance; }
}

  
 
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14

注:Spring 容器中所有的Bean都是单例的

代码请见:

https://github.com/XWxiaowei/JavaCode/tree/master/design-patterns

参考

https://www.cnblogs.com/V1haoge/p/6510196.html

文章来源: feige.blog.csdn.net,作者:码农飞哥,版权归原作者所有,如需转载,请联系作者。

原文链接:feige.blog.csdn.net/article/details/79848049

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。