首页 > 代码库 > 设计模式(二)单例模式(创建型)

设计模式(二)单例模式(创建型)

使用场景:

       一个类只能创建一个实例对象。如读取服务器配置文件的类,由单个实例对象直接读取。

实现流程:

      (1)、定义一个私有变量;

      (2)、将构造函数私有化;

      (3)、提供一个获取实例的公用方法;

     下面列出几种常见的实现模式,仅供参考:

      饿汉式单例:在类创建的时候就初始化实例对象,每次调用的时候都是获取同一对象实例,是线程安全的。

      实现类:

public class HungrySingleton {        private static HungrySingleton instance = new HungrySingleton();        private HungrySingleton(){};        public static HungrySingleton getInstance(){        return instance;    }}


      测试类:

public class HungrySingletonTest {        private class MyThread extends Thread{                @Override          public void run(){            System.out.println(HungrySingleton.getInstance().hashCode());        }            }        public static void main(String[] args) {          MyThread[] mts = new MyThread[10];          for(int i = 0 ; i < mts.length ; i++){              mts[i] = new HungrySingletonTest().new MyThread();          }                    for (int j = 0; j < mts.length; j++) {              mts[j].start();          }      }}


      测试结果:

技术分享

        从测试结果可以看出,该方式是线程安全的。

        普通懒汉式单例:创建类的时候不实例化对象,在调用获取实例方法的时候才创建对象。是线程不安全的。

        实现类: 

public class LazySingleton {        private static LazySingleton instance = null;        private LazySingleton(){};        public static LazySingleton getInstance(){        if(instance == null){            instance = new LazySingleton();        }        return instance;    }}

         测试类:

public class LazySingletonTest {        private class MyThread extends Thread{                @Override          public void run(){            System.out.println(LazySingleton.getInstance().hashCode());        }            }        public static void main(String[] args) {         MyThread[] mts = new MyThread[10];          for(int i = 0 ; i < mts.length ; i++){              mts[i] = new LazySingletonTest().new MyThread();          }                    for (int j = 0; j < mts.length; j++) {              mts[j].start();          }      }}

        测试结果:

技术分享

     从测试结果可以看出,该方式是线程不安全的。

      对线程不安全的懒汉式单例模式,有多种的解决方案。简单的如:在获取实例的公共方法里加上同步标识符synchronized。这样的话可以保证在多线程的环境下获取的实例是唯一的,但也相应地影响了效率。这里列举一种常规的解决方案——Double Check Locking双检查锁机制。

     双检查锁机制(DCL)

     实现类:

public class DclSingleton {        //使用volatile保证线程间可见性    private static volatile DclSingleton instance = null;        private DclSingleton(){};        public static  DclSingleton getInstance(){        if(instance == null){            synchronized(DclSingleton.class){                //二次检查                if(instance == null){                    instance = new DclSingleton();                }            }        }        return instance;    }}

       测试结果:
技术分享

    从测试结果可以看出,该方式是线程安全的,且将同步的范围限制到了最小。是推荐的一种单例实现方式。

 

设计模式(二)单例模式(创建型)