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

这段时间从头温习设计模式。记载下来,以便自己复习,也分享给大家。


[java]  view plain  copy
  1. package com.iter.devbox.singleton;  
  2.   
  3. /** 
  4.  * 饿汉式 
  5.  * @author Shearer 
  6.  * 
  7.  */  
  8. public class SingletonDemo1 {  
  9.       
  10.     // 类的静态成员变量只初始化一次,天然是线程安全的  
  11.     private static final SingletonDemo1 instance = new SingletonDemo1();  
  12.       
  13.     private SingletonDemo1(){}  
  14.       
  15.     public static SingletonDemo1 getInstance() {  
  16.         return instance;  
  17.     }  
  18.   
  19. }  
  20.   
  21.   
  22. package com.iter.devbox.singleton;  
  23.   
  24. /** 
  25.  * 懒汉式 
  26.  * @author Shearer 
  27.  * 
  28.  */  
  29. public class SingletonDemo2 {  
  30.       
  31.     // 类初始化时,不初始化这个对象(延迟加载,真正用的时候再创建)  
  32.     private static SingletonDemo2 instance;  
  33.       
  34.     private SingletonDemo2(){}  
  35.       
  36.     // 方法同步,调用效率低  
  37.     public static synchronized SingletonDemo2 getInstance() {  
  38.         if (null == instance)  
  39.             instance = new SingletonDemo2();  
  40.         return instance;  
  41.     }  
  42.   
  43. }  
  44.   
  45.   
  46. package com.iter.devbox.singleton;  
  47.   
  48. /** 
  49.  * 双重检查锁实现 
  50.  * 将同步放到if内部,提高了执行的效率。 
  51.  * 不必每次获取对象时都进行同步,只有第一次才同步。 
  52.  * 创建了以后就没有必要了。 
  53.  * 问题: 
  54.  * 由于编译器优化原因和JVM底层内部模型原因,偶尔会出问题,不建议使用。 
  55.  * @author Shearer 
  56.  * 
  57.  */  
  58. public class SingletonDemo3 {  
  59.       
  60.     private static SingletonDemo3 instance = null;  
  61.       
  62.     private SingletonDemo3(){}  
  63.       
  64.     public static SingletonDemo3 getInstance() {  
  65.         if (null == instance) {  
  66.             SingletonDemo3 sc;  
  67.             synchronized (SingletonDemo3.class) {  
  68.                 sc = instance;  
  69.                 if (null == sc) {  
  70.                     synchronized (SingletonDemo3.class) {  
  71.                         if (null == sc) {  
  72.                             sc = new SingletonDemo3();  
  73.                         }  
  74.                     }  
  75.                     instance = sc;  
  76.                 }  
  77.             }  
  78.         }  
  79.         return instance;  
  80.     }  
  81.   
  82. }  
  83.   
  84.   
  85. package com.iter.devbox.singleton;  
  86.   
  87. /** 
  88.  * 静态内部类实现方式(也是一种懒加载方式) 
  89.  * 这种方式:线程安全,调用效率高,并且实现了延迟加载 
  90.  * @author Shearer 
  91.  * 
  92.  */  
  93. public class SingletonDemo4 {  
  94.       
  95.     private static class SingletonClassInstance {  
  96.         private static final SingletonDemo4 instance = new SingletonDemo4();  
  97.     }  
  98.       
  99.     // 方法没有同步,调用效率高  
  100.     public static SingletonDemo4 getInstance() {  
  101.         return SingletonClassInstance.instance;  
  102.     }  
  103.       
  104.     private SingletonDemo4(){}  
  105. }  
  106.   
  107.   
  108. package com.iter.devbox.singleton;  
  109.   
  110. /** 
  111.  * 通过枚举实现单例模式(没有延迟加载) 
  112.  * 线程安全,调用效率高,不能延迟加载。 
  113.  * 并且可以天然的防止反射和反序列化漏洞 
  114.  * @author Shearer 
  115.  * 
  116.  */  
  117. public enum SingletonDemo5 {  
  118.     // 枚举元素,本身就是单例对象  
  119.         INSTANCE;  
  120.   
  121.     // 可以添加自己需要的操作  
  122.     public void singletonOperation() {  
  123.         System.out.println("枚举类里面的方法调用");  
  124.     }  
  125.       
  126. }  


测试多线程环境下5种创建单例模式的效率

[java]  view plain  copy
  1. package com.iter.devbox.singleton;  
  2.   
  3. import java.util.concurrent.CountDownLatch;  
  4.   
  5. /** 
  6.  * 测试多线程环境下5种创建单例模式的效率 
  7.  *  
  8.  * @author Shearer 
  9.  * 
  10.  */  
  11. public class Client4 {  
  12.   
  13.     public static void main(String[] args) throws Exception {  
  14.         long begin = System.currentTimeMillis();  
  15.   
  16.         int threadNum = 100// 100个线程(10个线程的情况下,运行多次有时候耗时为0!所以让线程多一点!)  
  17.         final CountDownLatch countDownLatch = new CountDownLatch(threadNum);  
  18.   
  19.         for (int i = 0; i < threadNum; i++) {  
  20.             new Thread(new Runnable() {  
  21.                 @Override  
  22.                 public void run() {  
  23.                     for (int i = 0; i < 100000; i++) {  
  24.                         Object obj1 = SingletonDemo1.getInstance(); // 15.饿汉式  
  25. //                      Object obj2 = SingletonDemo2.getInstance(); // 156.懒汉式  
  26. //                      Object obj3 = SingletonDemo3.getInstance(); // 16.双重检查锁,不要使用!  
  27. //                      Object obj4 = SingletonDemo4.getInstance(); // 15.静态内部类  
  28. //                      Object obj5 = SingletonDemo5.INSTANCE; // 16.枚举实现  
  29.                     }  
  30.                     countDownLatch.countDown();  
  31.                 }  
  32.             }).start();  
  33.         }  
  34.           
  35. /*      for (int i = 0; i < threadNum; i++) { 
  36.             new Thread(new MyRunnable(countDownLatch)).start(); 
  37.         }*/  
  38.           
  39.         countDownLatch.await(); // main线程阻塞,直到计数器变为0,才会继续往下执行  
  40.   
  41.         long end = System.currentTimeMillis();  
  42.         System.out.println("总耗时:" + (end - begin));  
  43.     }  
  44.   
  45. }  
  46.   
  47. /*class MyRunnable implements Runnable { 
  48.  
  49.     private CountDownLatch countDownLatch; 
  50.  
  51.     public MyRunnable(CountDownLatch countDownLatch) { 
  52.         this.countDownLatch = countDownLatch; 
  53.     } 
  54.  
  55.     @Override 
  56.     public void run() { 
  57.         for (int i = 0; i < 100000; i++) { 
  58. //          Object obj1 = SingletonDemo1.getInstance(); // 15.饿汉式 
  59. //          Object obj2 = SingletonDemo2.getInstance(); // 156.懒汉式 
  60. //          Object obj3 = SingletonDemo3.getInstance(); // 16.双重检查锁,不要使用! 
  61. //          Object obj4 = SingletonDemo4.getInstance(); // 31.静态内部类 
  62.             Object obj5 = SingletonDemo5.INSTANCE; // 16.枚举实现 
  63.         } 
  64.         countDownLatch.countDown(); 
  65.     } 
  66. }*/  


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

单例对象 占用 资源 少,不需要 延迟加载:

    枚举式 好于 饿汉式

单例对象 占用 资源 大,需要 延迟加载:

    静态内部类式 好于 懒汉式


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


就效率来说,由于懒汉式需要同步,效率最低。

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

如果单例对象占用资源大,需要延迟加载,使用静态内部类;


本文转自http://blog.csdn.net/hardwin/article/details/51480608,所有权利归原作者所有。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值