单例模式

来源:互联网 发布:51单片机的引脚功能 编辑:程序博客网 时间:2024/05/29 01:54

最近在看《剑指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