「这是我参与11月更文挑战的第1天,活动详情查看:2021最后一次更文挑战」
相关文章
设计模式系列:设计模式
前言
- 单例模式(Singleton) ,也叫单子模式,是一种常用的设计模式。在应用这个模式时,单例对象的类必须保证只有一个实例存在。许多时候,整个系统只需要拥有一个的全局对象,这样有利于我们协调系统整体的行为。比如在某个服务器程序中,该服务器的配置信息存放在一个文件中,这些配置数据由一个单例对象统一读取,然后服务进程中的其他对象再通过这个单例对象获取这些配置信息,显然,这种方式简化了在复杂环境下的配置管理。
- 单例模式就是为确保一个类只有一个实例,并为整个系统提供一个全局访问点的一种方法。
- 平时我们使用的Spring中的Bean默认就是单例的!尤其是javaConfig!
一、饿汉单例
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20java复制代码//饿汉单例模式
@Data
@Accessors(chain = true)
public class ehanSingleton {
//其他的属性,举例用的
private Integer readings = 0;//阅读量
private Integer collects = 0;//收藏量
private Integer likes = 0;//点赞量
//将自身的实例化对象设置成一个属性,并且加上final,static关键字修饰
private static final ehanSingleton singleton = new ehanSingleton();
//构造方法私有化---外部无法靠new来创建该对象
private ehanSingleton(){};
//公共的静态方法返回该实例,方便外部调用
public static ehanSingleton getInstance(){
return singleton;
}
}TestMain
+ 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
csharp复制代码public class SingletonMain {
public static void main(String[] args) {
ehanSingleton singleton = ehanSingleton.getInstance();
singleton.setReadings(singleton.getReadings()+1);
read(singleton);
singleton.setCollects(singleton.getCollects()+1);
singleton.setLikes(singleton.getLikes()+1);
System.out.println("阅读量为:"+singleton.getReadings());
System.out.println("收藏量为:"+singleton.getCollects());
System.out.println("点赞量为:"+singleton.getLikes());
}
public static void read(ehanSingleton singleton){
for (int i=0;i<100;i++){
singleton.setReadings(singleton.getReadings()+1);
}
}
}
- 执行结果
+ 
- 一上来就把单例对象创建出来了,要用的时候直接返回即可,这种可以说是单例模式中最简单的一种实现方式。
- 但是问题也比较明显。单例在还没有使用到的时候,初始化就已经完成了。
- 也就是说,如果程序从头到位都没用使用这个单例的话,单例的对象还是会创建。这就造成了不必要的资源浪费。所以不推荐这种实现方式。
二、懒汉单例
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
36java复制代码//懒汉单例模式
@Data
public class lanhanSingleton {
//其他的属性,举例用的
private Integer readings = 0;//阅读量
private Integer collects = 0;//收藏量
private Integer likes = 0;//点赞量
//将自身的实例化对象设置成一个属性,并且加上final,static关键字修饰
private static lanhanSingleton singleton = null;
//构造方法私有化---外部无法靠new来创建该对象
private lanhanSingleton(){};
//公共的静态方法返回该实例,方便外部调用,线程安全的1:同步代码块,效率低
public static synchronized lanhanSingleton getInstance(){
if (singleton == null){
singleton = new lanhanSingleton();
}
return singleton;
}
//公共的静态方法返回该实例,方便外部调用,线程安全的2:DCL 双检查锁机制
public static lanhanSingleton getInstance1(){
synchronized(lanhanSingleton.class){
//第一次检查instance是否被实例化出来,如果没有进入if块
if (singleton == null){
// 某个线程取得了类锁,实例化对象前第二次检查instance是否已经被实例化出来,如果没有,才最终实例出对象
if (singleton == null){
singleton = new lanhanSingleton();
}
}
}
return singleton;
}
}TestMain
+ 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
csharp复制代码public class SingletonMain {
public static void main(String[] args) {
lanhanSingleton instance = lanhanSingleton.getInstance();
instance.setReadings(instance.getReadings()+1);
read(instance);
instance.setCollects(instance.getCollects()+1);
instance.setLikes(instance.getLikes()+1);
System.out.println("阅读量为:"+instance.getReadings());
System.out.println("收藏量为:"+instance.getCollects());
System.out.println("点赞量为:"+instance.getLikes());
}
public static void read(lanhanSingleton singleton){
for (int i=0;i<100;i++){
singleton.setReadings(singleton.getReadings()+1);
}
}
}
- 执行结果
+ 
- 线程安全,调用效率不高,但是能延时加载。
- 那么饿汉和懒汉在我们实际使用中该如何选择呢?
+ 单例对象 占用资源少,不需要延时加载,枚举 好于 饿汉
+ 单例对象 占用资源多,需要延时加载,静态内部类 好于 懒汉式
路漫漫其修远兮,吾必将上下求索~
如果你认为i博主写的不错!写作不易,请点赞、关注、评论给博主一个鼓励吧~hahah
本文转载自: 掘金