码迷,mamicode.com
首页 > 其他好文 > 详细

设计模式(一)单例模式:2-懒汉模式

时间:2017-09-10 17:45:46      阅读:133      评论:0      收藏:0      [点我收藏+]

标签:log   void   cep   const   操作   好的   二进制   close   struct   

思想:

 

  相比于之前提及的饿汉模式,懒汉模式的实际应用场景更加广泛一些。

  因为在系统中,大多数的类都不必在一开始就初始化,在第一次投入使用的时候再初始化就可以了,这样做最大的好处无疑就是节省了大片的内存空间。

  设计的思想与饿汉模式类似,同样是持有一个自身的引用,只是将 new 的动作延迟到 getinstance() 方法中执行。

 

技术分享
 1 public class LazySingleton {
 2 
 3     private static LazySingleton instance;
 4 
 5     private LazySingleton() {
 6         
 7     }
 8 
 9     public static LazySingleton getInstance() {
10         if (instance == null) {
11             instance = new LazySingleton();
12         }
13         return instance;
14     }
15 
16 }
懒汉模式

 

考虑反射:

  

  类似的,可以在 private 的构造器中,增加对 instance 的非空判断,但是这么做,并不能完全阻止反射的入侵。

  如果在第一次调用 getInstance() 方法之前,实施反射入侵,那么就会打破单例的情况;反之,如果在第一次调用 getInstance() 方法之后,可以阻止反射的入侵。

 

技术分享
 1 @Test
 2     public void test() throws Exception {
 3         Constructor<?> constructor = LazySingleton.class.getDeclaredConstructor();
 4         constructor.setAccessible(true);
 5         // 反射入侵成功,必须优先反射
 6         LazySingleton singleton3 = (LazySingleton) constructor.newInstance();
 7         LazySingleton singleton1 = LazySingleton.getInstance();
 8         LazySingleton singleton2 = LazySingleton.getInstance();
 9         Assert.assertSame(singleton1, singleton2);
10         Assert.assertNotSame(singleton1, singleton3);
11     }
JUnit

 

考虑多线程:

 

  由于在 getInstance() 时,才会初始化对象,那么在高并发的情况下,同时多个线程调用 getInstance() 方法,就可以成功地构造多个对象,从而打破单例。

  有一种 DCL 双锁检测机制,就是专门用来处理这种情况的。

 

为什么必须是双锁,仅仅对方法加上 synchronized 修饰不行吗?

 

  单单使用 synchronized,理论上是可以禁止多线程情况下创建多个实例的。但是还需要考虑另外一种情况:指令重排。

  所有的 Java 代码,在 JVM 中最终都会转化为一系列二进制的操作指令,而 JVM 为了优化指令的执行效率,可能会进行一些重新排序,从而使代码并不是以我们所见到的形式自上而下执行。

  Java 语言提供了许多禁止指令重排的方式,而在这里,给 instance 加上另一层限制:volatile,则是最好的解决方案。

 

技术分享
 1 public class LazySingleton {
 2 
 3     private static volatile LazySingleton instance;
 4 
 5     private LazySingleton() {
 6         if (instance != null) {
 7             throw new IllegalStateException();
 8         }
 9     }
10 
11     public static synchronized LazySingleton getInstance() {
12         if (instance == null) {
13             instance = new LazySingleton();
14         }
15         return instance;
16     }
17 
18 }
完整的懒汉模式

 

设计模式(一)单例模式:2-懒汉模式

标签:log   void   cep   const   操作   好的   二进制   close   struct   

原文地址:http://www.cnblogs.com/jing-an-feng-shao/p/7501460.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!