单例模式

最近在看《剑指offer》这本书,虽说之前也看过,但是看得比较粗糙,决定重新看过。这本书也是公认的面试宝典,对程序猿找工作大有裨益,本书算法实现大部分是C/C++,也有部分C#代码。本人学习Java的,也能读懂C/C++和C#代码,但是我希望用Java实现一下本书算法,一来可以锻炼一下自己,二来通过比较不同语言实现同一算法的不同之处,体会一下其中奥妙。好吧,下面我们就来学习一下使用Java语言实现的Singleton模式。

         一、    只适用于单线程环境

 

public class Singleton1 
{
   
    private static Singleton1 instance = null;
   
    private Singleton1()
    {
      
    }
   
    public static Singleton1 Instance()
    {
       if(null == instance)
       {
           instance = new Singleton1();
           System.out.println("创建实例");
       }
       return instance;
    }
   
    public static void main(String[] args) {
       Singleton1.Instance();   //打印:创建实例
       Singleton1.Instance();   //不打印
       Singleton1.Instance();   //不打印
    }
 
}

         

        优点:适合单线程环境,当instance为null时才创建实例,避免重复创建。其中,将构造函数定义为私有函数是关键。

        缺点:当然是不适合多线程环境咯。


        二、    虽然在多线程环境中能工作但效率不高

public class TestThread extends Thread{
 
    @Override
    public void run()
    {     
       try
       {
           Singleton2.Instance();
           sleep(1000);
       } catch (InterruptedException e)
       {
           e.printStackTrace();
       }
    }
 
}

public class Singleton2 {
   
    private static Singleton2 instance = null;
    private static Object object = new Object();
   
    private Singleton2()
    {
      
    }
   
    public static Singleton2 Instance()
    {
       synchronized(object)
       {
           if(null == instance)
           {
              instance = new Singleton2();
              System.out.println("创建实例");
           }else
           {
              System.out.println("实例已存在");
           }
       }
       return instance;
    }
 
    public static void main(String[] args) {
       //循环创建线程,并调用Instance函数,最终"创建实例"只打印1次,代码正确。
       while(true)
       {
           new TestThread().start();
       }
    }
 
}

        缺点:当通过Instance函数得到Singleton2实例时,都会试图加上一个同步锁,但是加锁非常耗时,因此这里有待进一步改进。


        三、    加同步锁前后两次判断实例是否已存在

public class Singleton3 {
 
    private static Singleton3 instance = null;
    private static Object object = new Object();
 
    private Singleton3() {
 
    }
 
    public static Singleton3 Instance() {
       if (null == instance)
       {
           synchronized (object)
           {
              if (null == instance)
              {
                  instance = new Singleton3();
              }
           }
       }
       return instance;
    }

}

        缺点:代码复杂,易出错。


        四、    利用静态构造函数(也叫饿汉式)

public class Singleton4 {
   
    private static Singleton4 instance = new Singleton4();
   
    private Singleton4()
    {
      
    }
   
    public static Singleton4 Instance()
    {
       return instance;
    }
 
}

        缺点:没有实现按需创建实例,降低了内存使用效率。

        PS:与饿汉式相对的为懒汉式,即对象是方法被调用时才初始化,也叫做对象的延时加载。


        五、    实现按需创建实例

public class Singleton5 {
 
    private Singleton5()
    {
      
    }
   
    public static Singleton5 Instance()
    {
       return SingletonHelper.instance;
    }
   
    private static class SingletonHelper
    {
       private final static Singleton5 instance = new Singleton5();
    }
   
}

        此方法使用了静态内部类,是目前为止比较优秀的解法之一,真正做到了按需创建。



        写博文经验尚浅,如有错误之处,还望各位大神指出,谢谢。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值