几种单例模式

懒汉式:
饿汉式单例在类加载初始化时就创建好一个静态的对象供外部使用,除非系统重启,这个对象不会改变,所以本身就是线程安全的。
Singleton通过将构造方法限定为private避免了类在外部被实例化,在同一个虚拟机范围内,Singleton的唯一实例只能通过getInstance()方法访问。(事实上,通过Java反射机制是能够实例化构造方法为private的类的,会使Java单例实现失效)
public class Singleton {
   private Singleton(){
       System.out.println("构造函数Singleton1");
   }
   private static Singleton single = new Singleton();
   public static Singleton getInstance(){
       System.out.println("getInstance");
       return single;
   }

    public static void main(String[] args) {
        System.out.println("初始化");
        Singleton instance = Singleton.getInstance();
    }
}


饿汉式:
该示例虽然用延迟加载方式实现了懒汉式单例,但在多线程环境下会产生多个Singleton对象
public class SingletonDemo {
    private SingletonDemo (){
        System.out.println("构造函数Singleton2");
    }
    private static SingletonDemo single = null;
    public static SingletonDemo getInstance(){
        if (single ==null){
            System.out.println("getInstance");
            single = new SingletonDemo();
        }
        return single;
    }

    public static void main(String[] args) {
        System.out.println("初始化");
        SingletonDemo instance = SingletonDemo.getInstance();
    }
}

同步锁:
在方法上加synchronized同步锁或是用同步代码块对类加同步锁,此种方式虽然解决了多个实例对象问题,但是该方式运行效率却很低下,下一个线程想要获取对象,就必须等待上一个线程释放锁之后,才可以继续运行。
public class SynchronizedSingleton {
    private SynchronizedSingleton(){}
    private static SynchronizedSingleton synchronizedSingleton = null;

    public synchronized static SynchronizedSingleton getInstance(){
        if (synchronizedSingleton==null){
            synchronizedSingleton= new SynchronizedSingleton();
        }
        return synchronizedSingleton;
    }
}

双重检查锁:
使用双重检查锁进一步做了优化,可以避免整个方法被锁,只对需要锁的代码部分加锁,可以提高执行效率。
public class SingletonDoubleCheck {
    private SingletonDoubleCheck(){}

    private volatile static SingletonDoubleCheck single = null;

    public static SingletonDoubleCheck getInstance(){
        if (single==null){
            synchronized (SingletonDoubleCheck.class){
                if (single==null){
                    single = new SingletonDoubleCheck();
                }
            }
        }
        return single;
    }
}

静态内部类:
这种方式引入了一个内部静态类(static class),静态内部类只有在调用时才会加载,它保证了Singleton 实例的延迟初始化,又保证了实例的唯一性。它把singleton 的实例化操作放到一个静态内部类中,在第一次调用getInstance() 方法时,JVM才会去加载InnerObject类,同时初始化singleton 实例,所以能让getInstance() 方法线程安全。 
特点是:即能延迟加载,也能保证线程安全。
静态内部类虽然保证了单例在多线程并发下的线程安全性,但是在遇到序列化对象时,默认的方式运行得到的结果就是多例的。
public class StaticSingleton {
    private StaticSingleton(){}

    private static class InnerObject{
        private static StaticSingleton single = new StaticSingleton();
    }
    public static StaticSingleton getInstance(){
        return InnerObject.single;
    }
}

内部枚举类实现:
事实上,通过Java反射机制是能够实例化构造方法为private的类的。这也就是我们现在需要引入的枚举单例模式。
public class SingletonFactory {

    private enum EnumSingleton{
        Singleton;
        private SingletonInner singleton;

        private EnumSingleton(){
            singleton = new SingletonInner();
        }
        public SingletonInner getInstance(){
            return singleton;
        }
    }
    public static SingletonInner getInstance(){
        return EnumSingleton.Singleton.getInstance();
    }
}

class SingletonInner{
    public SingletonInner(){}
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

香扑扑

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值