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

使用场景:

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

实现流程:

      (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;
    }

}

       测试结果:

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

 

posted @ 2016-09-30 11:57  xuzhelin  阅读(155)  评论(0编辑  收藏  举报