1.饿汉式
饿汉式,从名字上也很好理解,就是“比较勤”,实例在初始化的时候就已经建好了,不管你有没有用到,都先建好了再说。
好处是没有线程安全的问题,坏处是浪费内存空间。
public class SingletonInstance {
//私有构造方法
private static SingletonInstance (){
}
//声明成员变量
private static SingletonInstance singletonInstance = new SingletonInstance();
//对外提供接口获取该实例
public static SingletonInstance getSingletonInstance(){
return singletonInstance ;
}
}
2.懒汉式
顾名思义就是实例在用到的时候才去创建,“比较懒”,用的时候才去检查有没有实例,如果有则返回,没有则新建。
有线程安全和线程不安全两种写法,区别就是synchronized关键字
public class SingletonInstance {
//私有构造方法
private SingletonInstance (){
}
//声明成员变量
private static SingletonInstance singletonInstance ;
//对外提供接口获取该实例
public static SingletonInstance getSingletonInstance(){
if(singletonInstance==null){
singletonInstance = new SingletonInstance();
}
return singletonInstance ;
}
}
3.double check lock(dcl)
双检锁,又叫双重校验锁,综合了懒汉式和饿汉式两者的优缺点整合而成。看上面代码实现中,特点是在synchronized关键字内外都加了一层 if 条件判断,这样既保证了线程安全,又比直接上锁提高了执行效率,还节省了内存空间。
java5之后使用 volatile关键字修饰变量,保证数据的正确性。
用happen-before规则重新审视DCL https://www.cnblogs.com/xun99/archive/2012/06/07/2540925.html
public class SingletonInstance {
//私有构造方法
private SingletonInstance (){
}
//声明成员变量
private volatile static SingletonInstance singletonInstance ;
//对外提供接口获取该实例
public static SingletonInstance getSingletonInstance(){
if(singletonInstance == null){
synchronized (SingletonInstance.class){
//两次判断是否为null
if(singletonInstance==null){
singletonInstance = new SingletonInstance();
}
}
}
return singletonInstance ;
}
}
4.静态内部类
为什么静态内部类可以解决多线程 https://www.cnblogs.com/shenwen/p/10707965.html
public class SingletonInstance {
//私有构造方法
private SingletonInstance (){
}
private static class Builder{
//声明成员变量
private static SingletonInstance singletonInstance = new SingletonInstance();
}
//对外提供接口获取该实例
public static SingletonInstance getSingletonInstance(){
return Builder.singletonInstance ;
}
}