abstract
保证对象只能被实例化一次的设计模式称为单例模式。
单例模式
饿汉模式
最简单的实现方法就是,一开始就初始化这个对象,并且将构造方法私有化。
1 | public class Singleton{ |
一开始就创建实例的设计方法也成为饿汉模式。
懒汉模式
还可以在调用的时候再初始化,称为懒汉模式。
1 | public class Singleton{ |
懒,就要付出代价。
基础懒汉模式并不是线程安全的,因为高并发下一个线程判断singleton为空时,会创建一个对象,但是创建对象是需要时间的,如果在创建期间另一个线程执行if判断时,条件成立,也会创建一个对象。对象的属性不变的情况下影响不大,但实例化的时候属性不同时,则有较大影响。
处理办法:
方法加同步锁。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17public class Singleton {
private static Singleton singleton = null;
private Singleton(){}
public synchronized static Singleton getInstance() {
try {
if(singleton == null){//懒汉式
singleton = new Singleton();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return singleton;
}
}
可能出现不安全的直接代码使用同步代码块包起来。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19public class Singleton {
private static Singleton singleton = null;
private Singleton(){}
public static Singleton getInstance() {
try {
if(singleton == null){//懒汉式
synchronized (Singleton.class) {
singleton = new Singleton();
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return singleton;
}
}
使用volatile关键字使线程共用,并进行二次判断。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21public class Singleton {
volatile private static Singleton singleton = null;
private Singleton(){}
public static Singleton getInstance() {
try {
if(singleton == null){//懒汉式
synchronized (Singleton.class) {
if(singleton == null){//二次检查
singleton = new Singleton();
}
}
}
} catch (InterruptedException e) {
e.printStackTrace();
}
return singleton;
}
}
静态内部类
项目启动的时候会优先加载静态资源。
1 | public class Singleton{ |
感觉和饿汉模式异曲同工。
静态代码块
静态代码块会被先执行,所以可以使用静态代码块的方式实现单例
1 | public class Singleton{ |