`
芝加哥09
  • 浏览: 60548 次
社区版块
存档分类
最新评论

动手写最优的单例模式

    博客分类:
  • Java
阅读更多

单例模式是码农常用的设计模式,但未必用的是最优的单例模式。

在此通过代码逐步分析出最优的单例模式,分享给各位码农。

 

一说到单例模式,我想最快想到的就是饿汉的单例模式,即:

public class Singleton {
    private Singleton () {
    }

    private static Singleton instance = new Singleton();

    public static Singleton getInstance() {
        return instance;
    }
}

这种单例模式,有一个不足,无法做到延迟加载,特别是当这个单例类不只是做一件事的时候同时这个单例的创建过程很慢的时候,它的不足体现得就更为突出。

 

 

另一种单例模式也比较容易想到,那就是懒汉单例模式,即:

public class LazySingleton {
    private LazySingleton() {
    }

    private static LazySingleton instance = null;

    public static synchronized LazySingleton getInstance() {
        if (instance == null) {
            instance = new LazySingleton();
        }
        return instance;
    }
}

 这种单例模式,也有一个很明显的不足,那就是引入同步关键字,在多线程的情况下,效率会低。

 

 

那该如何设计单例模式呢,其实我们可以通过内部类的形式来写单例模式,即:

public class StaticSingleton {
    private StaticSingleton() {
    }

    private static class SingletonHolder {
        private static StaticSingleton instance = new StaticSingleton();
    }

    public static StaticSingleton getInstance() {
        return SingletonHolder.instance;
    }
}

 这种单例模式,即可以实现延迟加载,同时又不会引入同步关键字,完美了。。。

2
8
分享到:
评论
22 楼 colin_i 2014-09-01  
其实最后的结果是不是就是比第一种方法多了延迟加载?可是多了延迟加载加载性能有多大区别呢,一个是在启动的时候加载,一个是在第一次调用的时候加载,都是加载一次而已啊?假设加载是要用10秒了,那把这个时间推迟到第一次调用,意义也不见得那么大吧?
21 楼 J2EE大鸟 2014-09-01  
嗯,我以前也被喷过。。哈哈
http://benworld.iteye.com/blog/1617976
20 楼 芝加哥09 2014-09-01  
xchd 写道
弱弱问一下,每次调用  public static StaticSingleton getInstance()都会执行一次new的操作吧,这好像无法达到单例的效果吧。

你测试一下就知道啊。。。被你吓到了。。。呵呵。。。
19 楼 xchd 2014-09-01  
弱弱问一下,每次调用  public static StaticSingleton getInstance()都会执行一次new的操作吧,这好像无法达到单例的效果吧。
18 楼 yoyo837 2014-09-01  
芝加哥09 写道
yoyo837 写道
我一般这么写
private volatile static SysConfig sysConfig = null;  
  
    public static SysConfig getInstance() {  
       [color=red] if (sysConfig == null) { [/color] 
            synchronized (SysConfig.class) {  
                 [color=red]if (sysConfig == null) {  [/color]
                     return sysConfig = new SysConfig();  
             [color=red]    }
            }  [/color]
        }  
        return sysConfig;  
    } 

这样好像会有问题吧,当这种情况,当第一个线程判断sysConfig为null了,则会new,当第二个线程在判断sysConfig是否为null时,第一线程还没有new完时,此时sysConfig还是null,则等下第二线程也会new的。。。这样就不能保证一个对像了。。。是不是啊。。。你再想想

new 在同步里面呀..
17 楼 芝加哥09 2014-09-01  
yoyo837 写道
我一般这么写
private volatile static SysConfig sysConfig = null;  
  
    public static SysConfig getInstance() {  
       [color=red] if (sysConfig == null) { [/color] 
            synchronized (SysConfig.class) {  
                 [color=red]if (sysConfig == null) {  [/color]
                     return sysConfig = new SysConfig();  
             [color=red]    }
            }  [/color]
        }  
        return sysConfig;  
    } 

这样好像会有问题吧,当这种情况,当第一个线程判断sysConfig为null了,则会new,当第二个线程在判断sysConfig是否为null时,第一线程还没有new完时,此时sysConfig还是null,则等下第二线程也会new的。。。这样就不能保证一个对像了。。。是不是啊。。。你再想想
16 楼 zhukewen_java 2014-09-01  
yoyo837 写道
我一般这么写
private volatile static SysConfig sysConfig = null;  
  
    public static SysConfig getInstance() {  
       [color=red] if (sysConfig == null) { [/color] 
            synchronized (SysConfig.class) {  
                 [color=red]if (sysConfig == null) {  [/color]
                     return sysConfig = new SysConfig();  
             [color=red]    }
            }  [/color]
        }  
        return sysConfig;  
    } 

一般情况下double check就够用了。不过在高并发的情况下还是有可能创建出多个实例
15 楼 芝加哥09 2014-09-01  
ahack 写道
芝加哥09 写道
ahack 写道
没有人说Initialization on demand holder不好,这TM不也得看具体的业务和环境?我兵法小,你吐槽啥?没写过java不知你的代码从哪儿copy出来的,呵呵。

我也是第一次碰到你这种奇葩,不过没事,碰多了就好,是吧。。。你的博客都是空的,嗨。。。你还是先分享分享你的博客吧,再来"指点江山",不要只会纸上谈兵。。。没意义啊。。。

博客么?http://javaweb.org/ 还好应该能打得开

嗯。。。不错,原来是大神啊,那就好好指点吧。。。
14 楼 yoyo837 2014-09-01  
我一般这么写
private volatile static SysConfig sysConfig = null;  
  
    public static SysConfig getInstance() {  
       [color=red] if (sysConfig == null) { [/color] 
            synchronized (SysConfig.class) {  
                 [color=red]if (sysConfig == null) {  [/color]
                     return sysConfig = new SysConfig();  
             [color=red]    }
            }  [/color]
        }  
        return sysConfig;  
    } 
13 楼 芝加哥09 2014-09-01  
ahack 写道
赶快喷,你写代码有多厉害。你们公司就你一个人。你写代码有多漂亮~呵呵

我没说我写的代码很厉害啊。。。
12 楼 zhukewen_java 2014-09-01  
芝加哥09 写道
ahack 写道
没有人说Initialization on demand holder不好,这TM不也得看具体的业务和环境?我兵法小,你吐槽啥?没写过java不知你的代码从哪儿copy出来的,呵呵。

我也是第一次碰到你这种奇葩,不过没事,碰多了就好,是吧。。。你的博客都是空的,嗨。。。你还是先分享分享你的博客吧,再来"指点江山",不要只会纸上谈兵。。。没意义啊。。。

芝加哥一看就是小菜鸟,没见过大场面,井底之蛙
11 楼 ahack 2014-09-01  
芝加哥09 写道
ahack 写道
没有人说Initialization on demand holder不好,这TM不也得看具体的业务和环境?我兵法小,你吐槽啥?没写过java不知你的代码从哪儿copy出来的,呵呵。

我也是第一次碰到你这种奇葩,不过没事,碰多了就好,是吧。。。你的博客都是空的,嗨。。。你还是先分享分享你的博客吧,再来"指点江山",不要只会纸上谈兵。。。没意义啊。。。

博客么?http://javaweb.org/ 还好应该能打得开
10 楼 ahack 2014-09-01  
赶快喷,你写代码有多厉害。你们公司就你一个人。你写代码有多漂亮~呵呵
9 楼 芝加哥09 2014-09-01  
ahack 写道
没有人说Initialization on demand holder不好,这TM不也得看具体的业务和环境?我兵法小,你吐槽啥?没写过java不知你的代码从哪儿copy出来的,呵呵。

我也是第一次碰到你这种奇葩,不过没事,碰多了就好,是吧。。。你的博客都是空的,嗨。。。你还是先分享分享你的博客吧,再来"指点江山",不要只会纸上谈兵。。。没意义啊。。。
8 楼 ahack 2014-09-01  
没有人说Initialization on demand holder不好,这TM不也得看具体的业务和环境?我兵法小,你吐槽啥?没写过java不知你的代码从哪儿copy出来的,呵呵。
7 楼 ahack 2014-09-01  
没那条件你发的不过是Initialization on demand holder,Double check 能慢多少?
private volatile static SysConfig sysConfig = null;

    public static SysConfig getInstance() {
        if (sysConfig == null) {
            synchronized (SysConfig.class) {
                return sysConfig = new SysConfig();
            }
        }
        return sysConfig;
    }

6 楼 darkness_t 2014-09-01  
ray_yui 写道
1.5后最优单例应该使用枚举

正解~
5 楼 芝加哥09 2014-09-01  
ahack 写道
加给synchronize判断下是否为空就算效率低下?别逗了好么

只能说你没有玩过大数据,当你的数量级到T或者P时,你用这个试试就知道啊。。。嗨。。。
4 楼 ahack 2014-09-01  
加给synchronize判断下是否为空就算效率低下?别逗了好么
3 楼 smiky 2014-09-01  
写很容易,原理呢?为什么不用引入synchronize?类加载的过程,什么情况下执行cinit?如果单单这样写一下有什么意义?

相关推荐

    自己动手写框架

    2. **设计模式**:如工厂模式、单例模式、观察者模式等,它们在框架设计中扮演着重要角色,用于解决特定问题并提供可复用的解决方案。 3. **模块化与分层设计**:如何组织代码使其易于维护和扩展,包括业务逻辑层、...

    自己动手模仿Hibernate写数据库框架

    2. **设计模式**:模仿Hibernate,我们需要理解其背后的设计模式,如工厂模式(用于创建数据库连接)、单例模式(控制数据库连接的数量)、代理模式(处理延迟加载)等。 3. **JDBC基础**:尽管我们要模仿Hibernate...

    工厂接口虚函数抽象函数单例DEMO

    4. **单例模式**:单例模式确保一个类只有一个实例,并提供全局访问点。在ASP.NET应用程序中,单例通常用于管理数据库连接、缓存或配置信息。单例可以通过私有构造函数和静态方法来实现,以防止多实例化。 结合这些...

    Head First 设计模式(中文完整版+附书源码)

    1. **单例模式**:在Java或任何面向对象的语言中,单例模式是一种确保一个类只有一个实例并提供全局访问点的设计模式。它常用于控制共享资源,如数据库连接池。书中通过“饿汉式”和“懒汉式”两种实现方式来解释...

    东北大学设计模式实验

    1. 创建型模式:包括单例模式、工厂模式(简单工厂、工厂方法、抽象工厂)、建造者模式和原型模式。它们关注于对象的创建过程,使得对象的实例化更加灵活,同时也隐藏了对象创建的复杂性。 2. 结构型模式:如适配器...

    我的设计模式学习

    创建型模式关注对象的创建过程,如单例模式、工厂方法模式、抽象工厂模式等;结构型模式关注如何组合现有组件以构建更复杂的结构,如代理模式、装饰器模式、适配器模式等;行为型模式则关注对象间的行为分配,如观察...

    C#设计模式 James Cooper

    2. **创建型模式**:这类模式主要关注对象的创建过程,包括单例模式、工厂方法模式、抽象工厂模式、建造者模式和原型模式。例如,单例模式确保一个类只有一个实例,而工厂方法则提供了创建对象的接口,但让子类决定...

    深入PHP:面向对象、模式与实践(第三版)高清PDF和完整源码下载.rar

    书中介绍了诸如工厂模式、单例模式、观察者模式、装饰器模式等多种设计模式。例如,工厂模式提供了一种创建对象的抽象方式,避免了代码对具体类的依赖;单例模式确保一个类只有一个实例,常用于控制资源的全局访问;...

    Objective-C编程之道:iOS 设计模式解析电子书和源代码

    1. **单例模式**:在Objective-C中,单例模式用于确保一个类只有一个实例,并提供一个全局访问点。这种模式在管理共享资源或者在整个应用程序中需要频繁使用的对象时特别有用,如网络连接或偏好设置管理者。 2. **...

    HeadFirst设计模式英文版

    这些模式包括但不限于单例模式(Singleton)、工厂方法模式(Factory Method)、抽象工厂模式(Abstract Factory)、建造者模式(Builder)、原型模式(Prototype)、适配器模式(Adapter)、装饰器模式(Decorator...

    C#23种设计模式_示例源代码及PDF

    单例模式: 而且自行实例化并向整个系统提供这个实 单例模式 单例模式确保某一个类只有一个实例, 例单例模式。单例模式只应在有真正的“单一实例”的需求时才可使用。 结构型模式 6、ADAPTER —在朋友聚会上碰到...

    设计模式实战:使用JAVA开发的飞机大战小游戏,包含了23种设计模式,.zip

    项目中包含的23种设计模式可能包括单例模式、工厂模式、观察者模式、策略模式、装饰器模式、适配器模式、代理模式、建造者模式、状态模式、命令模式、模板方法模式、访问者模式、桥接模式、组合模式、享元模式、迭代...

    工程模式demo

    对于初学者来说,通过研究和使用框架,可以更好地理解和应用设计模式,比如单例模式、装饰器模式、观察者模式等。 在这个“工程模式demo”中,很可能是通过具体的例子展示了如何在实际的框架中应用各种设计模式,让...

    精通python设计模式

    本书涵盖了多种经典的设计模式,如单例模式、工厂模式、观察者模式、装饰器模式、策略模式、代理模式等。单例模式确保一个类只有一个实例,常用于配置管理或线程控制;工厂模式提供了一种创建对象的最佳方式,避免了...

    Head First设计模式官方原码

    1. **创建型模式**:包括单例模式(Singleton)、工厂方法模式(Factory Method)、抽象工厂模式(Abstract Factory)、建造者模式(Builder)和原型模式(Prototype)。这些模式主要关注对象的创建过程,使得对象的...

    23种设计模式Demo

    1. **单例模式(Singleton)**:确保一个类只有一个实例,并提供全局访问点。在多线程环境下,正确实现单例需要考虑线程安全,防止多个线程同时创建实例。在Demo中,可能会展示如何通过双重检查锁定(Double-Checked...

    JAVA 模式培训教材

    1. 创建型模式:如单例模式(Singleton)、工厂模式(Factory)、抽象工厂模式(Abstract Factory)、建造者模式(Builder)、原型模式(Prototype)。这些模式主要关注对象的创建过程,帮助我们更好地管理对象的...

    GoF+23种设计模式解析附C++

    1. **创建型模式**(Creational Patterns):这类模式关注对象的创建过程,包括单例模式(Singleton)、工厂方法模式(Factory Method)、抽象工厂模式(Abstract Factory)、建造者模式(Builder)和原型模式...

    《JAVA设计模式》教学进度表

    在设计模式部分,课程将深入探讨创建型、结构型和行为型模式,包括但不限于简单工厂模式、工厂方法模式、抽象工厂模式、建造者模式、原型模式、单例模式、适配器模式、桥接模式、组合模式、装饰模式、外观模式、享元...

    head first java 设计模式源代码

    1. **单例模式**:确保一个类只有一个实例,并提供一个全局访问点。在Java中,通常使用双重检查锁定(Double-Check Locking)或枚举方式来实现。 2. **工厂模式**:提供一个接口用于创建对象,但让子类决定实例化哪...

Global site tag (gtag.js) - Google Analytics