欢迎来到淘文阁 - 分享文档赚钱的网站! | 帮助中心 好文档才是您的得力助手!
淘文阁 - 分享文档赚钱的网站
全部分类
  • 研究报告>
  • 管理文献>
  • 标准材料>
  • 技术资料>
  • 教育专区>
  • 应用文书>
  • 生活休闲>
  • 考试试题>
  • pptx模板>
  • 工商注册>
  • 期刊短文>
  • 图片设计>
  • ImageVerifierCode 换一换

    Java单例模式探究.pdf

    • 资源ID:69686201       资源大小:171.09KB        全文页数:9页
    • 资源格式: PDF        下载积分:15金币
    快捷下载 游客一键下载
    会员登录下载
    微信登录下载
    三方登录下载: 微信开放平台登录   QQ登录  
    二维码
    微信扫一扫登录
    下载资源需要15金币
    邮箱/手机:
    温馨提示:
    快捷下载时,用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)。
    如填写123,账号就是123,密码也是123。
    支付方式: 支付宝    微信支付   
    验证码:   换一换

     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    Java单例模式探究.pdf

    http:/ 疯狂大白菜 1/9 Java 单例模式探究单例模式探究单例模式探究单例模式探究 作为对象的创建模式作为对象的创建模式作为对象的创建模式作为对象的创建模式GOF95,单例模式确保某个类只有一个实例单例模式确保某个类只有一个实例单例模式确保某个类只有一个实例单例模式确保某个类只有一个实例,而且自行实例化并向而且自行实例化并向而且自行实例化并向而且自行实例化并向整个系统提供这个实例整个系统提供这个实例整个系统提供这个实例整个系统提供这个实例。这个类称为单例类这个类称为单例类这个类称为单例类这个类称为单例类。由定义可以总结出单例模式的要点有三个由定义可以总结出单例模式的要点有三个由定义可以总结出单例模式的要点有三个由定义可以总结出单例模式的要点有三个:一是单例类只能有一个实例一是单例类只能有一个实例一是单例类只能有一个实例一是单例类只能有一个实例;二是它必须自行创建这个实例二是它必须自行创建这个实例二是它必须自行创建这个实例二是它必须自行创建这个实例;三是它必须自行向整个系统三是它必须自行向整个系统三是它必须自行向整个系统三是它必须自行向整个系统提供这个实例提供这个实例提供这个实例提供这个实例。在计算机系统中,线程池、缓存、日志对象、对话框、打印机、显卡的驱动程序对象常被设计成单例。这些应用都或多或少具有资源管理器的功能。每台计算机可以有若干个打印机,但只能有一个 Printer Spooler,以避免两个打印作业同时输出到打印机中。每台计算机可以有若干通信端口,系统应当集中管理这些通信端口,以避免一个通信端口同时被两个请求同时调用。总之,选择单例模式就是为了避免不一致状态,避免政出多头。虽然从类图上看,单例模式是最简单的设计模式之一,但是真正正确地使用单例模式却不是那么简单的事。首先看一个经典的单例实现。public class Singleton private static Singleton uniqueInstance=null;private Singleton()/Exists only to defeat instantiation.public static Singleton getInstance()if(uniqueInstance=null)uniqueInstance=new Singleton();return uniqueInstance;/Other methods.Crazy Cabbagehttp:/ 疯狂大白菜 2/9 Singleton 通过将构造方法限定为 private 避免了类在外部被实例化,在同一个虚拟机范围内,Singleton 的唯一实例只能通过 getInstance()方法访问。(事实上,通过 Java 反射机制是能够实例化构造方法为 private 的类的,那基本上会使所有的 Java 单例实现失效。此问题在此处不做讨论,姑且掩耳盗铃地认为反射机制不存在。)但是以上实现没有考虑线程安全问题。所谓线程安全是指:如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。或者说:一个类或者程序所提供的接口对于线程来说是原子操作或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题。显然以上实现并不满足线程安全的要求,在并发环境下很可能出现多个 Singleton 实例。有很多种方法可以实现线程安全的单例模式,下面逐一介绍:1 一步到位的饿汉单例类 饿汉式单例类是在 Java 语言里实现得最为简便的单例类。在类被加载时,就会将自己实例化。public class Singleton private static Singleton uniqueInstance=new Singleton();private Singleton()/Exists only to defeat instantiation.public static Singleton getInstance()return uniqueInstance;/other methods.2 改造经典模式 首先是最简单最直接的改造。public class Singleton private static Singleton uniqueInstance=null;private Singleton()/Exists only to defeat instantiation.public synchronized static Singleton getInstance()if(uniqueInstance=null)uniqueInstance=new Singleton();Crazy Cabbagehttp:/ 疯狂大白菜 3/9 return uniqueInstance;/Other methods.通过 synchronized 关键字,同步了不同线程对 getInstance()的访问。这就是所谓的懒汉模式。与饿汉式单例类不同的是,懒汉式单例类在第一次被引用时将自己实例化。这种简单实现的问题在于,每次访问 getInstance()都需要同步操作,而事实上同步只在第一次访问时有意义。为了避免不必要的同步操作,在 JDK1.5以后可以使用一种双重检查加锁的方法。public class Singleton /volatile is very important for uniqueInstance consistency.private volatile static Singleton uniqueInstance=null;private Singleton()/Exists only to defeat instantiation.public static Singleton getInstance()/first check no need to synchronize.if(uniqueInstance=null)/second check need to synchronize,but only run limit times.synchronized(Singleton.class)if(uniqueInstance=null)uniqueInstance=new Singleton();return uniqueInstance;/Other methods.volatile 确保 uniqueInstance 被初始化为单例后的改变对所有线程可见,多线程能够正确处理 uniqueInstance 变量。getInstance()中包含两次判空操作,第一次判空每次访问都会执行,而第二次判空只在初始访问存在大量并发的情况下出现。通过两次判空避免了不必要的线程同步。之所以限制必须在 JDK1.5 后使用是因为,之前的 Java 存储模型不能保证 volatile 语义的完全正确实现。为了突破Crazy Cabbagehttp:/ 疯狂大白菜 4/9 这种限制Effective Java中给出了一种精妙的解决方法,充分利用了 Java 虚拟机的特性。public class Singleton /an inner class holder the uniqueInstance.private static class SingletonHolder static final Singleton uniqueInstance=new Singleton();private Singleton()/Exists only to defeat instantiation.public static Singleton getInstance()return SingletonHolder.uniqueInstance;/Other methods.When the getInstance method is invoked for the first time,it reads SingletonHolder.uniqueInstance for the first time,causing the SingletonHolder class to get initialized.The beauty of this idiom is that the getInstance method is not synchronized and performs only a field access,so lazy initialization adds practically nothing to the cost of access.A modern VM will synchronize field access only to initialize the class.Once the class is initialized,the VM will patch the code so that subsequent access to the field does not involve any testing or synchronization.3 登记式单例类 登记式单例类是 GoF 为了克服饿汉式单例类及懒汉式单例类均不可继承的缺点而设计的。public class RegSingleton static private HashMap m_registry=new HashMap();static RegSingleton x=new RegSingleton();m_registry.put(x.getClass().getName(),x);protected RegSingleton()Crazy Cabbagehttp:/ 疯狂大白菜 5/9 public static RegSingleton getInstance(String name)if(name=null)name=com.javapatterns.singleton.demos.RegSingleton;if(m_registry.get(name)=null)try m_registry.put(name,Class.forName(name).newInstance();catch(ClassNotFoundException cnf)System.out.println(Couldnt find class +name);catch(InstantiationException ie)System.out.println(Couldnt instantiate an object of type+name);catch(IllegalAccessException ia)System.out.println(Couldnt access class +name);return(RegSingleton)(m_registry.get(name);/sub-class implements RegSingleton.public class RegSingletonChild extends RegSingleton public RegSingletonChild()static public RegSingletonChild getInstance()return(RegSingletonChild)RegSingleton .getInstance(com.javapatterns.singleton.demos.RegSingletonChild);Crazy Cabbagehttp:/ 疯狂大白菜 6/9 public String about()return Hello,I am RegSingletonChild.;在 GoF 原始的例子中,并没有 getInstance()方法,这样得到子类必须调用的getInstance(String name)方法并传入子类的名字,因此很不方便。加入 getInstance()方法的好处是 RegSingletonChild 可以通过这个方法,返还自已的实例。而这样做的缺点是,由于数据类型不同,无法在 RegSingleton 提供这样一个方法。由于子类必须允许父类以构造子调用产生实例,因此,它的构造子必须是公开的。这样一来,就等于允许了以这样方式产生实例而不在父类的登记中。这是登记式单例类的一个缺点。GoF 曾指出,由于父类的实例必须存在才可能有子类的实例,这在有些情况下是一个浪费。这是登记式单例类的另一个缺点。现在我们已经知道如何实现线程安全的单例类和如何使用一个注册表去在运行期指定单例类名,接着让我们考查一下如何安排类载入器、处理序列化以及单例模式与 ThreadLocal的关系。?Classloaders 在许多情况下,使用多个类载入器是很普遍的-包括 servlet 容器-所以不管你在实现你的单例类时是多么小心你都最终可以得到多个单例类的实例。如果你想要确保你的单例类只被同一个的类载入器装入,那你就必须自己指定这个类载入器;例如:private static Class getClass(String classname)throwsClassNotFoundException ClassLoader classLoader=Thread.currentThread().getContextClassLoader();if(classLoader=null)classLoader=Singleton.class.getClassLoader();return(classLoader.loadClass(classname);这个方法会尝试把当前的线程与那个类载入器相关联;如果 classloader 为 null,这个方法会使用与装入单例类基类的那个类载入器。这个方法可以用 Class.forName()代替。?序列化 如果你序列化一个单例类,然后两次重构它,那么你就会得到那个单例类的两个实例,除非你实现 readResolve()方法,像下面这样:public class Singleton implements java.io.Serializable Crazy Cabbagehttp:/ 疯狂大白菜 7/9 public static Singleton INSTANCE=new Singleton();protected Singleton()/Exists only to thwart instantiation.private Object readResolve()return INSTANCE;上面的单例类实现从 readResolve()方法中返回一个唯一的实例;这样无论 Singleton 类何时被重构,它都只会返回那个相同的单例类实例。无论是 singleton,或是其他实例受控(instance-controlled)的类,必须使用 readResolve 方法来保护“实例控制的约束”。从本质上来讲,readResovle 方法把一个 readObject 方法从一个事实上的公有构造函数变成一个事实上的公有静态工厂。对于那些禁止包外继承的类而言,readResolve 方法作为保护性的 readObject 方法的一种替代,也是非常有用的。?ThreadLocal 在利用 Hibernate 开发 DAO 模块时,我们和 Session 打的交道最多,所以如何合理的管理Session,避免 Session 的频繁创建和销毁,对于提高系统的性能来说是非常重要的,以下代码实现了 Session 管理功能。import org.hibernate.HibernateException;import org.hibernate.Session;import org.hibernate.cfg.Configuration;public class HibernateSessionFactory private static String CONFIG_FILE_LOCATION=/hibernate.cfg.xml;private static final ThreadLocal threadLocal=new ThreadLocal();private static Configuration configuration=new Configuration();private static org.hibernate.SessionFactory sessionFactory;private static String configFile=CONFIG_FILE_LOCATION;static try Crazy Cabbagehttp:/ 疯狂大白菜 8/9 configuration.configure(configFile);sessionFactory=configuration.buildSessionFactory();catch(Exception e)System.err.println(%Error Creating SessionFactory%);e.printStackTrace();private HibernateSessionFactory()public static Session getSession()throws HibernateException Session session=(Session)threadLocal.get();if(session=null|!session.isOpen()if(sessionFactory=null)rebuildSessionFactory();session=(sessionFactory!=null)?sessionFactory.openSession():null;threadLocal.set(session);return session;/Other methods.我们知道 Session 是由 SessionFactory 负责创建的,而 SessionFactory 的实现是线程安全的,采用前面提到的“饿汉模式”创建单例。多个并发的线程可以同时访问一个SessionFactory 并从中获取 Session 实例,那么 Session 是否是线程安全的呢?很遗憾,答案是否定的。Session 中包含了数据库操作相关的状态信息,那么说如果多个线程同时使用一个 Session 实例进行 CRUD,就很有可能导致数据存取的混乱,你能够想像那些你根Crazy Cabbagehttp:/ 疯狂大白菜 9/9 本不能预测执行顺序的线程对你的一条记录进行操作的情形吗?以上代码使用ThreadLocal 模式的解决了这一问题。只要借助上面的工具类获取 Session 实例,我们就可以实现线程范围内的 Session 共享,从而避免了线程中频繁的创建和销毁 Session 实例。当然,不要忘记在用完后关闭 Session。ThreadLocal 和线程同步机制相比有什么优势呢?ThreadLocal 和线程同步机制都是为了解决多线程中相同变量的访问冲突问题。在同步机制中,通过对象的锁机制保证同一时间只有一个线程访问变量。这时该变量是多个线程共享的,使用同步机制要求程序慎密地分析什么时候对变量进行读写,什么时候需要锁定某个对象,什么时候释放对象锁等繁杂的问题,程序设计和编写难度相对较大。而 ThreadLocal 则从另一个角度来解决多线程的并发访问。ThreadLocal 会为每一个线程提供一个独立的变量副本,从而隔离了多个线程对数据的访问冲突。因为每一个线程都拥有自己的变量副本,从而也就没有必要对该变量进行同步了。ThreadLocal 提供了线程安全的共享对象,在编写多线程代码时,可以把不安全的变量封装进 ThreadLocal。由于 ThreadLocal 中可以持有任何类型的对象,低版本 JDK 所提供的 get()返回的是 Object对象,需要强制类型转换。但 JDK 5.0 通过泛型很好的解决了这个问题,在一定程度地简化 ThreadLocal 的使用。概括起来说,对于多线程资源共享的问题,同步机制采用了“以时间换空间”的方式,而ThreadLocal 采用了“以空间换时间”的方式。前者仅提供一份变量,让不同的线程排队访问,而后者为每一个线程都提供了一份变量,因此可以同时访问而互不影响。ThreadLocal 是解决线程安全问题一个很好的思路,它通过为每个线程提供一个独立的变量副本解决了变量并发访问的冲突问题。在很多情况下,ThreadLocal 比直接使用synchronized 同步机制解决线程安全问题更简单、更方便,且结果程序拥有更高的并发性。ThreadLocal 在 Spring 中发挥着重要的作用,在管理 request 作用域的 Bean、事务管理、任务调度、AOP 等模块都出现了它们的身影,起着举足轻重的作用。不过在使用线程池的情况下,使用 ThreadLocal 应该慎重,因为线程池中的线程是可重用的。Crazy Cabbage

    注意事项

    本文(Java单例模式探究.pdf)为本站会员(asd****56)主动上传,淘文阁 - 分享文档赚钱的网站仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知淘文阁 - 分享文档赚钱的网站(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    关于淘文阁 - 版权申诉 - 用户使用规则 - 积分规则 - 联系我们

    本站为文档C TO C交易模式,本站只提供存储空间、用户上传的文档直接被用户下载,本站只是中间服务平台,本站所有文档下载所得的收益归上传人(含作者)所有。本站仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。若文档所含内容侵犯了您的版权或隐私,请立即通知淘文阁网,我们立即给予删除!客服QQ:136780468 微信:18945177775 电话:18904686070

    工信部备案号:黑ICP备15003705号 © 2020-2023 www.taowenge.com 淘文阁 

    收起
    展开