• 单例模式(Singleton)


    定义:确保某一个类只有单一的实例,而且自行实例化,向整个系统提供一个实例,这个类叫单例类,提供全局的访问方法。

    单例模式有三个要点:

      1、某个类只能有一个实例

      2、它必须自行创建这个实例

      3、必须自行向整个系统提供这个实例

    单例类在消耗资源较大的重型对象中使用较多,如数据库连接的CollectionPool对象,Hibernate中的Configuration对象。Windows上的资源管理器也是由单例模式实现的(只能打开一个资源管理器)。

    Singleton的一般实现

     1 Class Singleton{
     2     private static Singleton instance=null;
     3     private Singleton(){}
     4     public static Singleton getInstance(){
     5         if(instance==null){
     6             instance=new Singleton();
     7         }
     8         return instance;
     9     }
    10 }
    Singleton

      以上代码,在单线程的环境下不会有什么问题,但当多个线程同时访问时(由于单例类一般需要大量初始化工作),可能会导致在没有完全初始化之前,其他线程已经进行if语句判断,并为true。这样的情况会出现多个单例类的实例

    线程不安全Singleton的解决方案:

    A:EagerSingleton:饿汉单例模式,单例对象的初始化在类加载的时候完成

    1 class EagerSingleton{
    2     //同理,亦可以使用static代码块实现初始化
    3     private static EagerSingleton instance= new EagerSingleton();
    4     private EagerSingleton(){}
    5     public static EagerSingleton getInstance(){
    6         return instance;
    7     }
    8 }
    EagerSingleton

      以上代码,虽然解决了线程安全问题,但是,类加载的时间会延长

    B:LazySingleton:懒汉单例模式,利用synchronized对getInstance方法进行线程锁定

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

      以上代码,可以很好的解决线程安全问题,而且也使用了延迟加载技术,但是每次调用getInstance都需要进行线程锁定判断,大大降低了系统性能

    C:Double-Check Locking:双重检查锁定,利用volatile保证多线程下对成员变量的正确处理,在利用双重判断加同步实现LazySingleton

     1 class LazySingleton{
     2     private volatile static LazySingleton instance=null;
     3     private LazySingleton(){}
     4     synchronized public static LazySingleton getInstance(){
     5         if(instance==null){
     6             synchronized(LazySingleton.class){
     7                 if(instance==null){
     8                     instance=new LazySingleton();
     9                 }
    10             }
    11         }
    12         return instance;
    13     }
    14 }
    Double-Check

      以上代码,同样对系统的性能有影响,而且volatile会屏蔽虚拟机的一些代码优化

    D:IoDH:使用静态内部类实现延迟加载及线程安全

    1 class Singleton{
    2     private Singleton(){}
    3     private static class Hoder{
    4         private final static Singleton instance=new Singleton();
    5     }
    6     public static Singleton getInstance(){
    7         return Holder.instance;
    8     }
    9 }
    IoDH

      以上代码,既可以保证延迟加载,又可以保证线程安全,不影响系统性能,实际上,采用内部类的方法可以将实例化及返回封装成原子操作,这样就完全不需要考虑线程安全问题了,综上所述,这是一种较好的单例模式实现方法

    E:单元素的枚举类型:Effective java中提及,实现Singleton的最佳方法

      更加简洁,无偿提供了序列化机制,绝对防止多次实例化,即使是在面对复杂序列化或者反射攻击的时候。虽然这种方法还没有广泛使用。。。所以,笔者不提倡。。。

    ----------------------------------------------------------------------------------------------------------------------------------------------------------------

    不足之处,还望指正

  • 相关阅读:
    Java之集合类应用总结
    Java的HashMap和HashTable
    Java安全通信:HTTPS与SSL
    字符串如何排序
    HashMap泛型编程
    Java之currenHashMap
    Android游戏开发:游戏框架的搭建(1)
    Java安全通信概述
    嵌入式linux学习步骤
    图片水平无缝滚动的代码
  • 原文地址:https://www.cnblogs.com/toddy-bear/p/3370417.html
Copyright © 2020-2023  润新知