zoukankan      html  css  js  c++  java
  • (转)单例模式的多种写法

    转载:http://cantellow.iteye.com/blog/838473  (本文有简单修改其内容)

    第一种(懒汉,线程安全):

    Java代码  
    1. public class Singleton {  
    2.     private static Singleton instance;  
    3.     private Singleton (){}  
    4.     public static synchronized Singleton getInstance() {  
    5.     if (instance == null) {  
    6.         instance = new Singleton();  
    7.     }  
    8.     return instance;  
    9.     }  
    10. }  

     这种写法能够在多线程中很好的工作,而且看起来它也具备很好的lazy loading,但是,遗憾的是,效率很低,99%情况下不需要同步。

    第二种(饿汉):

    Java代码  
    1. public class Singleton {  
    2.     private static Singleton instance = new Singleton();  
    3.     private Singleton (){}  
    4.     public static Singleton getInstance() {  
    5.     return instance;  
    6.     }  
    7. }  

     这种方式基于classloder机制避免了多线程的同步问题,不过,instance在类装载时就实例化,虽然导致类装载的原因有很多种,在单例模式中大多数都是调用getInstance方法, 但是也不能确定有其他的方式(或者其他的静态方法)导致类装载,这时候初始化instance显然没有达到lazy loading的效果。

     

    第三种(静态内部类):

    Java代码  
    1. public class Singleton {  
    2.     private static class SingletonHolder {  
    3.     private static final Singleton INSTANCE = new Singleton();  
    4.     }  
    5.     private Singleton (){}  
    6.     public static final Singleton getInstance() {  
    7.     return SingletonHolder.INSTANCE;  
    8.     }  
    9. }  

     这种方式同样利用了classloder的机制来保证初始化instance时只有一个线程.

    第四种(枚举): 

    Java代码  
    1. public enum Singleton {  
    2.     INSTANCE;  
    3.     public void whateverMethod() {  
    4.     }  
    5. }  

     这种方式是Effective Java作者Josh Bloch 提倡的方式,它不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象,可谓是很坚强的壁垒啊,不过,个人认为由于1.5中才加入enum特性,用这种方式写不免让人感觉生疏,在实际工作中,我也很少看见有人这么写过。

    总结

    有两个问题需要注意:

    1.如果单例由不同的类装载器装入,那便有可能存在多个单例类的实例。假定不是远端存取,例如一些servlet容器对每个servlet使用完全不同的类装载器,这样的话如果有两个servlet访问一个单例类,它们就都会有各自的实例。

    2.如果Singleton实现了java.io.Serializable接口,那么这个类的实例就可能被序列化和复原。不管怎样,如果你序列化一个单例类的对象,接下来复原多个那个对象,那你就会有多个单例类的实例。

    对第一个问题修复的办法是:

    Java代码  
    1. private static Class getClass(String classname)      
    2.                                          throws ClassNotFoundException {     
    3.       ClassLoader classLoader = Thread.currentThread().getContextClassLoader();     
    4.       
    5.       if(classLoader == null)     
    6.          classLoader = Singleton.class.getClassLoader();     
    7.       
    8.       return (classLoader.loadClass(classname));     
    9.    }     
    10. }  

     对第二个问题修复的办法是:

    Java代码  
    1. public class Singleton implements java.io.Serializable {     
    2.    public static Singleton INSTANCE = new Singleton();     
    3.       
    4.    protected Singleton() {     
    5.         
    6.    }     
    7.    private Object readResolve() {     
    8.             return INSTANCE;     
    9.       }    
    10. }   
  • 相关阅读:
    ASP.NET MVC 重点教程一周年版 第二回 UrlRouting
    ASP.NET MVC 重点教程一周年版 第三回 Controller与View
    DynamicData for Asp.net Mvc留言本实例 下篇 更新
    Asp.net MVC视频教程 18 单选与复选框
    使用ASP.NET MVC Futures 中的异步Action
    ASP.NET MVC RC 升级要注意的几点
    ATL、MFC、WTL CString 的今生前世
    msvcprt.lib(MSVCP90.dll) : error LNK2005:已经在libcpmtd.lib(xmutex.obj) 中定义
    关于Windows内存的一些参考文章
    Windows访问令牌相关使用方法
  • 原文地址:https://www.cnblogs.com/latteyan/p/7909917.html
Copyright © 2011-2022 走看看