JAVA设计模式之单例设计模式

        单例模式,是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例的特殊类。通过单例模式可以保证系统中,应用该模式的类一个类只有一个实例。即一个类只有一个对象实例。

  在JAVA中实现单例,必须了解JAVA内存机制,JAVA中实例对象存在于堆内存中,若要实现单例,必须满足两个条件:

  1.限制类实例化对象。即只能产生一个对象。

  2.保证外部能够获取这个对象,否则对象创建将毫无意义

  如要满足以上两个条件,可以将构造方法私有化,然后在类中提供一个静态方法获取类实例。代码如下

 1 public class SingleTon {
 2 
 3     private static final SingleTon single = new SingleTon();  
 4 
 5     private SingleTon() {
 6 
 7     }
 8 
 9     /**
10      * 获取一个单例对象。
11      * @return 返回SingleTon对象。
12      */
13     public static SingleTon getInstance() {
14         return single;
15     }
16 
17 }

  JVM加载SingleTon后,会对静态成员做默认初始化,此时new SingleTon()创建的对象会赋值给single,类只会被加载一次,即使多次调用getInstance方法,所返回的对象也不会改变。single字段在初始化的过程中,对象就创建了,所以以上案例的代码又称为饿汉式。从对象的生命周期来看,类一旦加载,对象会在堆中立即创建,会浪费内存空间,因此,又存在另外一种称为懒汉式的单例设计模式。代码如下:

  

 1 public class SingleTonLazy {
 2 
 3     private static SingleTonLazy single = null;
 4 
 5     private SingleTonLazy() {
 6 
 7     }
 8 
 9     /**
10      * 获取一个单例对象。
11      * @return 返回SingleTon对象。
12      */
13     public static SingleTonLazy getInstance() {
14 
15         if (single == null) {
16             single = new SingleTonLazy();
17         }
18   
19         return single;
20 
21     }
22 
23 }

 

  SingleTonLazy在被加载进方法区后,不会立即创建对象,而是直到getInstance方法被调用以后,对象才会被创建。这种方式可以节约内存空间,但是也存在着线程安全问题,当线程A执行到判断对象为null,此时线程B获得执行权,线程B判断对象为null,此时线程A重新获得执行权,创建对象,线程B恢复,继续创建对象。将代码修改如下,使用同步锁解决线程安全问题。

  

 1 public class SingleTonLazy {
 2 
 3     private static SingleTonLazy single = null;
 4 
 5     private final static Lock lock = new ReentrantLock();
 6 
 7     private SingleTonLazy() {
 8 
 9     }
10 
11     /**
12      * 获取一个单例对象。
13      * @return 返回SingleTon对象。
14      */
15     public static SingleTonLazy getInstance() {
16 
17         if (single != null) {
18             return single;
19         }
20 
21         lock.lock();
22         if (single == null) {
23             single = new SingleTonLazy();
24         }
25         lock.unlock();
26 
27         return single;
28 
29     }
30 }

  总结:饿汉式与懒汉式各有优缺点,但是相对来说,占用内存空间比让cpu判断锁的开销要小,所以饿汉式更使用一些。

 

posted @ 2018-04-05 01:48  浮生_如梦  阅读(102)  评论(0编辑  收藏  举报