设计模式学习笔记-单例模式

来源:互联网 发布:坐船去美国 知乎 编辑:程序博客网 时间:2024/05/22 05:04

一:简介

1. 在我们的一些应用中,比如缓存池,数据库连接池,线程池,一些应用服务实例等事件上我们通常需要保证在一个类中只能被创建一个对象,这这时候就需要单例模式。

    2. 单例模式主要有3个特点,:
2.1 单例类确保自己只有一个实例。
2.2 单例类必须自己创建自己的实例。
2.3 单例类必须为其他对象提供唯一的实例。

   3. 实现方式:懒汉单例类饿汉单例类
3.1  懒汉式单例类
     对于懒汉模式,我们可以这样理解:该单例类非常懒,只有在自身需要的时候才会行动,从来不知道及早做好准备。它在需要对象的时候,才判断是否已有对象,如果没有就立即创建一个对象,然后返回,如果已有对象就不再创建,立即返回。
懒汉模式只在外部对象第一次请求实例的时候才去创建。
3.2  饿汉式单例
     对于饿汉模式,我们可以这样理解:该单例类非常饿,迫切需要吃东西,所以它在类加载的时候就立即创建对象。

3.3  懒汉模式和饿汉模式的优缺点:
     懒汉模式,它的特点是运行时获得对象的速度比较慢,但加载类的时候比较快。它在整个应用的生命周期只有一部分时间在占用资源。
         饿汉模式,它的特点是加载类的时候比较慢,但运行时获得对象的速度比较快。它从加载到应用结束会一直占用资源。

 

二:代码演示

     1.  懒汉式是最简单的一种,原理就是保证该类构造方法的私有,然后通过方法返回这个唯一创造的对象,方式属于线程安全的!

 

public class Singleton {     private Singleton(){      }      private static Singletoninstance = new Singleton();      private static SingletongetInstance(){         returninstance;     } } 
2.  饿汉式在开始初始化时不创建对象实体,只在需要到时创建。方式属于线程不安全

public class Singleton     {            private Singleton(){         }         private static Singleton instance;         public static Singleton getInstance(){             if(instance == null){                 return instance = new Singleton();             }else{                 return instance;             }         }     }   

3.  高并发状态下上一种很容易产生多个实例,所以我们需要寻找线程安全的方法,首先最容易就是添加synchronized关键字

public class ThreadSafeSingelton {     //variables and constructors…     public static synchronized ThreadSafeSingelton getInstance() {         if(instatnce ==null){             instatnce = new ThreadSafeSingelton();         }         return instatnce;     } } <span style="color:#33cc00;"></span>
4.  虽然添加了synchronized关键字实现了线程安全,但是在多线程高并发状态下性能却很受影响,在上一个代码片中synhchronized关键字对整体方法都加了synchronized,这是没有必要的,我们可以提取成这样,形成Doule-CheckLocking

public class DoubleCheckSingleton {     private volatile static DoubleCheckSingleton instatnce = null;     //constructors     public static DoubleCheckSingleton getInstance() {         if (instatnce == null) {   //check if it is created.             synchronized (DoubleCheckSingleton.class) {  //synchronize creation block                 if (instatnce == null)   //double check if it is created                     instatnce = new DoubleCheckSingleton();             }         }         return instatnce;     } } 

5. 当然,上述已经达到目标,除此之外我们还有一种方法也可以实现同样的目标,称为Initialization on demand holder模式

public class LazyLoadedSingleton {     private LazyLoadedSingleton() {        }        private static class LazyHolder {  //holds the singleton class               private static final LazyLoadedSingleton singletonInstatnce = new LazyLoadedSingleton();        }        public static LazyLoadedSingleton getInstance() {               return LazyHolder.singletonInstatnce;        } } 
6. 如果单例类实现了Serializable接口,这时我们得特别注意,因为我们知道在默认情况下,每次反序列化(Desierialization)总会创建一个新的实例对象,这样一个系统会出现多个对象供使用。解决办法可以在readResolve()方法里做文章,此方法在反序列化完成之前被执行,我们在此方法里替换掉反序列化出来的那个新的实例,让其指向内存中的那个单例对象即可

import java.io.Serializable; public class SerialibleSingleton implements Serializable {     private static final long serialVersionUID = -6099617126325157499L;     static SerialibleSingleton singleton = new SerialibleSingleton();     private SerialibleSingleton() {     }     // This method is called immediately after an object of this class is deserialized.     // This method returns the singleton instance.     private Object readResolve() {         return singleton;     } } 




0 0
原创粉丝点击