我的日常

登录/注册
您现在的位置:论坛 资料库 JAVA开发 > 你真的了解单例模式吗?
总共48086条微博

动态微博

查看: 1894|回复: 3

你真的了解单例模式吗?

[复制链接]
admin    

1244

主题

544

听众

1万

金钱

管理员

  • TA的每日心情

    2021-2-2 11:21
  • 签到天数: 36 天

    [LV.5]常住居民I

    管理员

    跳转到指定楼层
    楼主
    发表于 2016-06-19 14:10:37 |只看该作者 |倒序浏览
           本文介绍了为何需要单例模式,单例模式的设计要点,饿汉和懒汉的区别,并通过实例介绍了实现单例模式的九种实现方式及其优缺点。

    为何需要单例模式


    对于系统中的某些类来说,只有一个实例很重要,例如,一个系统只能有一个窗口管理器或文件系统;一个系统只能有一个计时工具或ID(序号)生成器。


    单例模式设计要点


    保证该类只有一个实例。将该类的构造方法定义为私有方法,这样其他处的代码就无法通过调用该类的构造方法来实例化该类的对象
    提供一个该实例的访问点。一般由该类自己负责创建实例,并提供一个静态方法作为该实例的访问点


    饿汉 vs. 懒汉


    饿汉 声明实例引用时即实例化
    懒汉 静态方法第一次被调用前不实例化,也即懒加载。对于创建实例代价大,且不定会使用时,使用懒加载模式可以减少开销


    实现单例模式的九种方法



    1. 线程不安全的懒汉 - 多线程不可用
    1. public class Singleton {
    2.   private static Singleton INSTANCE;
    3.   private Singleton() {};
    4.   public static Singleton getInstance() {
    5.     if (INSTANCE == null) {
    6.       INSTANCE = new Singleton();
    7.     }
    8.     return INSTANCE;
    9.   }
    10. }
    复制代码

    优点:达到了Lazy Loading的效果
    缺点:只有在单线程下能保证只有一个实例,多线程下有创建多个实例的风险


    2. 同步方法下的懒汉 - 可用,不推荐
    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. }
    复制代码
    优点:线程安全,可确保正常使用下(不考虑通过反射调用私有构造方法)只有一个实例
    缺点:每次获取实例都需要申请锁,开销大,效率低


    3. 同步代码块下的懒汉 - 不可用
    1. public class Singleton {
    2.   private static Singleton INSTANCE;
    3.   private Singleton() {};
    4.   public static Singleton getInstance() {
    5.     if (INSTANCE == null) {
    6.       synchronized (Singleton.class) {
    7.         INSTANCE = new Singleton();
    8.       }
    9.     }
    10.     return INSTANCE;
    11.   }
    12. }
    复制代码


    优点:不需要在每次调用时加锁,
    缺点:虽然使用了`synchronized`,但本质上是线程不安全的。


    4. 不正确双重检查(Double Check)下的懒汉 - 不推荐


    1. public class Singleton {
    2.   private static Singleton INSTANCE;
    3.   private Singleton() {};
    4.   public static Singleton getInstance() {
    5.     if (INSTANCE == null) {
    6.       synchronized(Singleton.class){
    7.         if(INSTANCE == null) {
    8.           INSTANCE = new Singleton();
    9.         }
    10.       }
    11.     }
    12.     return INSTANCE;
    13.   }
    14. }
    复制代码
    优点:使用了双重检查,很大程度上避免了线程不安全,同时也避免了不必要的锁开销
    缺点:依然存在创建多个实例的可能。因为每个线程都有自己的一份拷贝,并不能保证实例化后将INSTANCE的引用拷回主内存,不能保证对其它线程立即可见,所以仍然有可能造成多个实例被创建

    5. 正确双重检查(Double Check)下的懒汉 - 推荐
    1. public class Singleton {
    2.   private static volatile Singleton INSTANCE;
    3.   private Singleton() {};
    4.   public static Singleton getInstance() {
    5.     if (INSTANCE == null) {
    6.       synchronized (Singleton.class) {
    7.         if (INSTANCE == null) {
    8.           INSTANCE = new Singleton();
    9.         }
    10.       }
    11.     }
    12.     return INSTANCE;
    13.   }
    14. }
    复制代码
    优点:使用了双重检查,同时使用`volatile`修饰`INSTANCE`,避免由于多线性同步和可见性问题造成的多实例
    缺点:NA

    6. 静态常量 饿汉 - 推荐
    1. public class Singleton {
    2.   private static final Singleton INSTANCE = new Singleton();
    3.   private Singleton() {};
    4.   public static Singleton getInstance() {
    5.     return INSTANCE;
    6.   }
    7. }
    复制代码

    优点:实现简单,无线程同步问题
    缺点:在类装载时完成实例化。若该实例一直未被使用,则会造成资源浪费

    7. 静态代码块 饿汉 可用
    1. public class Singleton {
    2.   private static Singleton INSTANCE;
    3.   static{
    4.     INSTANCE = new Singleton();
    5.   }
    6.   private Singleton() {};
    7.   public static Singleton getInstance() {
    8.     return INSTANCE;
    9.   }
    10. }
    复制代码
    优点:无线程同步问题
    缺点:类装载时创建实例,无Lazy Loading。实例一直未被使用时,会浪费资源

    8. 静态内部类 推荐
    1. public class Singleton {
    2.   private Singleton() {};
    3.   public static Singleton getInstance() {
    4.     return InnerClass.INSTANCE;
    5.   }
    6.   
    7.   private static class InnerClass {
    8.     private static final Singleton INSTANCE = new Singleton();
    9.   }
    10. }
    复制代码
    优点:无线程同步问题,实现了懒加载(Lazy Loading)。因为只有调用`getInstance`时才会装载内部类,才会创建实例
    缺点:NA

    9. 枚举 不推荐
    1. public enum Singleton {
    2.   INSTANCE;
    3.   public void whatSoEverMethod() {
    4. }
    复制代码





    优点:无线程同步问题,且能防止通过反射创建新的对象
    缺点:使用的是枚举,而非类。同时单一实例的访问点也不是一般单例模式的静态方法





    原文转自 Jason's Blog

    科帮网 1、本主题所有言论和图片纯属会员个人意见,与本社区立场无关
    2、本站所有主题由该帖子作者发表,该帖子作者与科帮网享有帖子相关版权
    3、其他单位或个人使用、转载或引用本文时必须同时征得该帖子作者和科帮网的同意
    4、帖子作者须承担一切因本文发表而直接或间接导致的民事或刑事法律责任
    5、本帖部分内容转载自其它媒体,但并不代表本站赞同其观点和对其真实性负责
    6、如本帖侵犯到任何版权问题,请立即告知本站,本站将及时予与删除并致以最深的歉意
    7、科帮网管理员和版主有权不事先通知发贴者而删除本文


    JAVA爱好者①群:JAVA爱好者① JAVA爱好者②群:JAVA爱好者② JAVA爱好者③ : JAVA爱好者③

    46

    主题

    1

    听众

    584

    金钱

    三袋弟子

    该用户从未签到

    80后

    沙发
    发表于 2016-10-30 13:57:06 |只看该作者
    不错,总结的非常全面,,根据 数量 来进行 划分,,除了 单例,我们还可以实现 双例 模式, 多例 模式, 没有数量限制的 new 模式,new 模式的 变体   工厂方法模式~~~
    已有 1 人评分帮币 收起 理由
    admin + 5 神马都是浮云

    总评分:  帮币 + 5         查看全部评分

    回复

    使用道具 举报

    46

    主题

    1

    听众

    584

    金钱

    三袋弟子

    该用户从未签到

    80后

    板凳
    发表于 2016-10-30 13:57:46 |只看该作者
    这样按照  实例 数量 进行 划分的 模式 就全部 囊括其中了~~~
    回复

    使用道具 举报

    26

    主题

    2

    听众

    816

    金钱

    五袋长老

    该用户从未签到

    地板
    发表于 2016-11-05 08:45:14 |只看该作者
    学习了,最近面试遇到过单例模式的,再遇到就不担心了
    回复

    使用道具 举报

    快速回复
    您需要登录后才可以回帖 登录 | 立即注册

       

    关闭

    站长推荐上一条 /1 下一条

    发布主题 快速回复 返回列表 联系我们 官方QQ群 科帮网手机客户端
    快速回复 返回顶部 返回列表