设计模式学习05----之单例模式
单例模式,是我们最常用也最熟悉的一种设计模式,其使用要注意线程安全。
定义
单例模式:顾名思义,就是在应用中有且只有一个实例。一般类似于计数器类的都必须是单例,多例会导致计数结果不准。
一般而言,其分为饿汉式和懒汉式。
懒汉式
懒汉式:顾名思义,就是不在系统加载时创建类的实例。而是在调用时才去一次性创建。
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
- 点赞
- 收藏
- 关注作者
评论(0)