单例模式的5种实现方式,以及在多线程环境下5种建立单例模式的效率

/** 
 * 饿汉式 
 * @author yinwei.Liu
 * 
 */  
public class SingletonDemo1 {  
      
    // 类的静态成员变量只初始化一次,自然是线程安全的  
    private static final SingletonDemo1 instance = new SingletonDemo1();  
      
    private SingletonDemo1(){}  
      
    public static SingletonDemo1 getInstance() {  
        return instance;  
    }  
  
}  
   
  
/** 
 * 懒汉式 
 * @author yinwei.Liu
 * 
 */  
public class SingletonDemo2 {  
      
    // 类初始化时,不初始化这个对象(延迟加载,真正用的时候再建立)  
    private static SingletonDemo2 instance;  
      
    private SingletonDemo2(){}  
      
    // 方法同步,调用效率低  
    public static synchronized SingletonDemo2 getInstance() {  
        if (null == instance)  
            instance = new SingletonDemo2();  
        return instance;  
    }  
  
}  
  
  
/** 
 * 双重检查锁实现 
 * 将同步放到if内部,提升了执行的效率。 
 * 没必要每次获取对象时都进行同步,只有第一次才同步。 
 * 建立了之后就没有必要了。 
 * 问题: 
 * 因为编译器优化缘由和JVM底层内部模型缘由,偶尔会出问题,不建议使用。 
 * @author yinwei.Liu
 * 
 */  
public class SingletonDemo3 {  
      
    private static SingletonDemo3 instance = null;  
      
    private SingletonDemo3(){}  
      
    public static SingletonDemo3 getInstance() {  
        if (null == instance) {  
            SingletonDemo3 sc;  
            synchronized (SingletonDemo3.class) {  
                sc = instance;  
                if (null == sc) {  
                    synchronized (SingletonDemo3.class) {  
                        if (null == sc) {  
                            sc = new SingletonDemo3();  
                        }  
                    }  
                    instance = sc;  
                }  
            }  
        }  
        return instance;  
    }  
  
}  
  
   
  
/** 
 * 静态内部类实现方式(也是一种懒加载方式) 
 * 这种方式:线程安全,调用效率高,而且实现了延迟加载 
 * @author yinwei.Liu
 * 
 */  
public class SingletonDemo4 {  
      
    private static class SingletonClassInstance {  
        private static final SingletonDemo4 instance = new SingletonDemo4();  
    }  
      
    // 方法没有同步,调用效率高  
    public static SingletonDemo4 getInstance() {  
        return SingletonClassInstance.instance;  
    }  
      
    private SingletonDemo4(){}  
}  
  
   
  
/** 
 * 经过枚举实现单例模式(没有延迟加载) 
 * 线程安全,调用效率高,不能延迟加载。 
 * 而且能够自然的防止反射和反序列化漏洞 
 * @author yinwei.Liu
 * 
 */  
public enum SingletonDemo5 {  
    // 枚举元素,自己就是单例对象  
        INSTANCE;  
  
    // 能够添加本身须要的操做  
    public void singletonOperation() {  
        System.out.println("枚举类里面的方法调用");  
    }  
      
}  

 

 

测试多线程环境下5种建立单例模式的效率
import java.util.concurrent.CountDownLatch;  
/** 
 * 测试多线程环境下5种建立单例模式的效率 
 *  
 * @author yinwei.Liu 
 * 
 */  
public class Test {  
  
    public static void main(String[] args) throws Exception {  
        long begin = System.currentTimeMillis();  
  
        int threadNum = 100; // 100个线程(10个线程的状况下,运行屡次有时候耗时为0!因此让线程多一点!)  
        final CountDownLatch countDownLatch = new CountDownLatch(threadNum);  
  
        for (int i = 0; i < threadNum; i++) {  
            new Thread(new Runnable() {  
                @Override  
                public void run() {  
                    for (int i = 0; i < 100000; i++) {  
                        Object obj1 = SingletonDemo1.getInstance(); // 15.饿汉式  
//                      Object obj2 = SingletonDemo2.getInstance(); // 156.懒汉式  
//                      Object obj3 = SingletonDemo3.getInstance(); // 16.双重检查锁,不要使用!  
//                      Object obj4 = SingletonDemo4.getInstance(); // 15.静态内部类  
//                      Object obj5 = SingletonDemo5.INSTANCE; // 16.枚举实现  
                    }  
                    countDownLatch.countDown();  
                }  
            }).start();  
        }  
          
/*      for (int i = 0; i < threadNum; i++) { 
            new Thread(new MyRunnable(countDownLatch)).start(); 
        }*/  
          
        countDownLatch.await(); // main线程阻塞,直到计数器变为0,才会继续往下执行  
  
        long end = System.currentTimeMillis();  
        System.out.println("总耗时:" + (end - begin));  
    }  
  
}  
  
/*class MyRunnable implements Runnable { 
 
    private CountDownLatch countDownLatch; 
 
    public MyRunnable(CountDownLatch countDownLatch) { 
        this.countDownLatch = countDownLatch; 
    } 
 
    @Override 
    public void run() { 
        for (int i = 0; i < 100000; i++) { 
//          Object obj1 = SingletonDemo1.getInstance(); // 15.饿汉式 
//          Object obj2 = SingletonDemo2.getInstance(); // 156.懒汉式 
//          Object obj3 = SingletonDemo3.getInstance(); // 16.双重检查锁,不要使用! 
//          Object obj4 = SingletonDemo4.getInstance(); // 31.静态内部类 
            Object obj5 = SingletonDemo5.INSTANCE; // 16.枚举实现 
        } 
        countDownLatch.countDown(); 
    } 
}*/  

 

 /*

选择哪一种方式实现单例模式?结论:

单例对象 占用 资源 少,不须要 延迟加载:
枚举式 好于 饿汉式
单例对象 占用 资源 大,须要 延迟加载:
静态内部类式 好于 懒汉式

 
经常使用的两种方式,饿汉式和懒汉式,单例对象占用资源少时,选用饿汉式;反之,用懒汉式。

就效率来讲,因为懒汉式须要同步,效率最低。

若是单例对象占用资源少,无需延迟加载,使用饿汉式或枚举式;

若是单例对象占用资源大,须要延迟加载,使用静态内部类;*/
相关文章
相关标签/搜索