单例模式的三种实现方式:
1. 同步getInstance()方法
这是保证可行的最直接做法。如果没有性能层面的考虑,可以直接采用该方法。同步一个方法,可能造成程序执行效率下降100倍。每个线程在进入这个方法之前,必须等候别的线程离开该方法。
public class Singleton {
private static Singleton singleton;
private Singleton() {};
public static synchronized Singleton getInstance() {
if (singleton == null) {
singleton = new Singleton();
}
return singleton;
}
}
2. Eagerly 静态初始化实例
如果实例需要在一开始就被初始化,或者在创建和运行时方面的负担不太繁重,那么可以采用此种方法。
public class Singleton {
private static Singleton singleton = new Singleton();
private Singleton() {};
public static Singleton getInstance() {
return singleton;
}
}
3. 双重检查加锁 (Double-checked locking)
采用DCL,首先检查实例是否已经创建了,如果尚未创建,“才”进行同步创建。这样,只有在第一次执行的时候才会同步。volatile关键字确保,singleton在被初始化后,对于其他线程立即可见。
public class Singleton {
private static volatile Singleton singleton;
private Singleton() {};
public static Singleton getInstance() {
if (singleton == null) {
synchronized (singleton) {
//进入区块后,再检查一次,防止多线程并发情况下被创建多次
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
volatile关键字:
volatile关键字支持需要Java5及以上的版本。
一旦一个共享变量(类的成员变量、类的静态成员变量)被volatile修饰之后,那么就具备了两层语义:
1)保证了不同线程对这个变量进行操作时的可见性,即一个线程修改了某个变量的值,这新值对其他线程来说是立即可见的。
2)禁止进行指令重排序。
网友评论