单例模式的意思就是只有一个实例。单例模式确保某一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。这个类称为单例类。分为饿汉模式和懒汉模式
饿汉模式是在类加载时便初始化,这里不做详谈,而懒汉模式则是在有人使用它的时候加载。主要针对懒汉模式对其进行不断优化。
- 懒汉模式 1 – 不安全:一开始是没有对象的,有人需要的时候,才会实例化。而且第一次使用的时候进行实例化,以后不再进行。线程不安全。(典型的判断-修改模式,不安全)
public class 懒汉模式1 {
private static 懒汉模式1 instance = null;
public static 懒汉模式1 getInstance() {
if (instance == null) {
instance = new 懒汉模式1();
}
return instance;
}
}
- 懒汉模式 2 --较为安全:说它不安全主要因为5-6句不安全,给这两句加锁,就可变为线程安全
public class 懒汉模式2 {
private static 懒汉模式2 instance = null;
public static 懒汉模式2 getInstance() {
synchronized (懒汉模式2.class) {
if (instance == null) {
instance = new 懒汉模式2();
}
}
return instance;
}
}
**分析:**性能不高,因为假如只是竞争一会儿,时间扩展到一百年一万年,这时间没有竞争,那么加锁便会降低性能。
3. 懒汉模式 3 – 安全+高效,存在重排序隐患:二次判断。修改了加锁的时机,保证多线程只在竞争时候加锁,没有竞争时候不加锁。
public class 懒汉模式3 {
private static 懒汉模式3 instance = null;
public static 懒汉模式3 getInstance() {
if (instance == null) {
//运行时出现竞争现象,就会进入以下代码块中,否则不进入,即不竞争不加锁
synchronized (懒汉模式3.class) {
//如果此时指针还是为空
if (instance == null) {
instance = new 懒汉模式3();
}
}
}
return instance;
}
}
- 懒汉模式 4 – 安全+高效+没有隐患。可能存在重排序问题。可能其他线程会得到一个初始化一半的对象,为此,加入 volatile 可以保证 instance = new 懒汉模式() 初始化是完全的。
public class 懒汉模式4 {
private static volatile 懒汉模式4 instance = null;
public static 懒汉模式4 getInstance() {
if (instance == null) {
synchronized (懒汉模式4.class) {
if (instance == null) {
instance = new 懒汉模式4();
}
}
}
return instance;
}
}