1 单例类只有一个实例对象
2 该单例类必须有单了类自行创建
3 单例类对外提供一个访问该单例的全局访问点
1 饿汉式 hungry loading
类加载到内存后就实例化一个单例,JVM保证线程安全;唯一缺点是不管是否用到类转载时就完成实例化。
public class T01_Hungry {
private static final T01_Hungry INSTANCE = new T01_Hungry();
private T01_Hungry() {
}
public static T01_Hungry getInstance() {
return INSTANCE;
}
}
2 懒汉式 lazy loading
使用时才初始化,但存在线程不安全问题。
/**
* 单例模式——懒汉式
*
* 问题:线程不安全
*/
public class T02_Lazy {
private static T02_Lazy instance;
private T02_Lazy() {
}
public static T02_Lazy getInstance() {
if (instance == null) {
instance = new T02_Lazy();
}
return instance;
}
}
3 懒汉式改进1:getInstance方法加synchronize进行同步
通过synchronized关键字来解决线程不安全问题,但是效率会降低。
/**
* 懒汉式改-进加: getInstance方法加synchronize进行同步
*
* 问题:整个方法加锁,锁太粗,效率偏低
*/
public class T03_LazyWithSynchronize {
private static T03_LazyWithSynchronize instance;
private T03_LazyWithSynchronize() {
}
public static synchronized T03_LazyWithSynchronize getInstance() {
if (instance == null) {
instance = new T03_LazyWithSynchronize();
}
return instance;
}
}
4 懒汉式改进2:双重检查 DCL
/**
* 懒汉式改 - 双重检查
*/
public class T04_LazyWithdoubleCheck {
// volatile 语义:保证指令不乱序执行,高并发下避免获取到半加载的实例
private static volatile T04_LazyWithdoubleCheck instance;
private T04_LazyWithdoubleCheck() {
}
public static T04_LazyWithdoubleCheck getInstance() {
if (instance == null) {
synchronized (T04_LazyWithdoubleCheck.class) {
if (instance == null) {
instance = new T04_LazyWithdoubleCheck();
}
}
}
return instance;
}
}
5 静态内部类方式
JVM保证单例,加载外部类是不会加载内部类,可以实现懒加载
/**
* 单例模式-静态内部类
*/
public class T05_StaticInnerClass {
private T05_StaticInnerClass() {
}
private static class Inner {
private static final T05_StaticInnerClass INSTANCE = new T05_StaticInnerClass();
}
public static T05_StaticInnerClass getInstance() {
return Inner.INSTANCE;
}
}
6 枚举单例
不仅可以解决线程同步问题,还可以防止反序列化。
/**
* 单例模式 - 枚举实现
*
*/
public enum T06_Enum {
/**
* 单例
*/
INSTANCE;
}