餓漢模式
類加載時便實例化,線程安全。
public class HungrySingleton {
private static HungrySingleton hungrySingleton = new HungrySingleton();
private HungrySingleton(){
}
public static HungrySingleton getInstance(){
return hungrySingleton;
}
}
懶漢模式
使用時再初始化,但線程不安全
public class LazySingleton {
private static LazySingleton singleton;
private LazySingleton(){
}
public static LazySingleton getInstance(){
if (singleton !=null){
return singleton;
}
singleton = new LazySingleton();
return singleton;
}
}
懶漢模式使用synchronized同步
public class SyncLazySingleton {
private static SyncLazySingleton singleton;
private SyncLazySingleton(){
}
public synchronized static SyncLazySingleton getInstance(){
if (singleton !=null){
return singleton;
}
singleton = new SyncLazySingleton();
return singleton;
}
}
雙重檢查
對象的引用需要加volatile關鍵字箍铲。因為對象的創(chuàng)建是非原子的。會經歷一下三個步驟鬓椭。
- 申請內存
- 調用構造方法
- 對象引用指向申請的內存
其中2,3步驟可能發(fā)生重排序颠猴。多線程情況下可能導致一個不完整的對象提前暴露关划。
public class DoubleCheckSingleton {
private volatile static DoubleCheckSingleton singleton;
private DoubleCheckSingleton(){}
public static DoubleCheckSingleton getInstance(){
if (singleton == null){
synchronized (DoubleCheckSingleton.class){
if (singleton == null){
singleton = new DoubleCheckSingleton();
}
}
}
return singleton;
}
}
靜態(tài)內部類
線程安全,且延時加載翘瓮,如果需要序列化和反序列化會生成多個對象贮折。
public class InnerClassSingleton {
private static class SingletonHandler{
private static InnerClassSingleton singleton = new InnerClassSingleton();
}
private InnerClassSingleton(){
}
public static InnerClassSingleton getInstance(){
return SingletonHandler.singleton;
}
}
枚舉方式
線程安全,且延時加載春畔,如果需要序列化和反序列化不會生成多個對象脱货。
public class EnumSingleton {
public enum Singleton{
INSTANCE;
private EnumSingleton singleton;
Singleton(){
singleton = new EnumSingleton();
}
public EnumSingleton getSingleton(){
return singleton;
}
}
public static void main(String[] args) {
System.out.println(Singleton.INSTANCE.getSingleton());
}
}