单例模式可保证一个类只有一个实例,并提供一个类方法来访问该实例。

class  SingletonDemo
{
    private static SingletonDemo singletonDemo;
    //构造函数的访问权限设置为private,防止外部自己构造实例
    private SingletonDemo(){}
    
    public static SingletonDemo getInstance(){
        if(singletonDemo == null){
            singletonDemo = new SingletonDemo();
        }
        return singletonDemo;
    }
}

以上方法仅适用于单线程的情景下,因为在多线程情景下,会发生创建多个类实例的情况。
如下图:
图片描述

  • 第一种:

    class SingletonDemo1
    {

       private static SingletonDemo1 singletonDemo1;
    
       private SingletonDemo1(){}
       //通过增加synchronized关键字来加锁
       public static synchronized SingletonDemo1 getInstance(){
           if(singletonDemo1 == null){
               singletonDemo1 = new SingletonDemo1();
           }
           return singletonDemo1;
       }

    }

此方法的缺点:每次调用getInstance方法都要加锁,会造成很大的开销,是程序的效率大大降低,因此这不是最好的方法。

  • 第二种:

    class SingletonDemo2
    {

       //急切创建实例,通过添加static关键字来使每次加载类的时候就创建实例
       private static SingletonDemo2 singletonDemo2 = new SingletonDemo2();
    
       private SingletonDemo2(){}
       
       public static SingletonDemo2 getInstance(){
           return singletonDemo2;
       }

    }

  • 第三种:

    class SingletonDemo3
    {

       //通过添加volatile关键字来保证实例的同步
       private volatile static SingletonDemo3 singletonDemo3;
    
       private SingletonDemo3(){}
       
       public static SingletonDemo3 getInstance(){
           if(singletonDemo3 == null){
               //这里二次加锁
               synchronized(SingletonDemo3.class){
                   if(singletonDemo3 == null)
                       singletonDemo3 = new SingletonDemo3();
           }
           return singletonDemo3;
       }

    }

注意:这种方法只能应用于jdk1.5及以后的版本,之前的版本是不适用的,因为之前的版本中jvm对于volatile关键字的实现会是双重加锁的失效。


DrXin
14 声望0 粉丝

程序员