你真的会用单例模式吗

作者: TedYin被占用了 | 来源:发表于2016-03-13 14:51 被阅读305次

转载请注明出处:http://tedyin.me/2016/03/13/singlton-pattern/

今天给大家介绍一下单例模式,就是这个出场率特别高的模式,是个程序员基本都用过他,没用过至少也都知道他。可是我们真的了解他吗?

单例模式通常的实现方式分为以下两种:

饿汉式

public class Singleton{
    private static Singleton instance = new Singleton();
    private Singleton(){}
    public static Singleton newInstance(){
        return instance;
    }
    public void doSomething(){
        // Do something ...
     }
}

饿汉式是最简单的实现方式,这种实现方式适合那些在初始化时就要用到单例的情况,这种方式简单粗暴,如果不单例初始化非常快,而且占用内存非常小的时候这种方式是比较合适的,直接在应用启动时加载并初始化。
但是,如果单例初始化的操作耗时比较长而应用对于启动速度又有要求,或者单例的占用内存比较大,再或者单例只是在某个特定场景的情况下才会被使用,而一般情况下是不会使用时,使用饿汉式的单例模式就是不合适的,这时候就需要用到懒汉式的方式去按需延迟加载单例。

懒汉式

public class Singleton{
    private static Singleton instance = null;    
    private Singleton(){}
    public static newInstance(){
        if(null == instance){
            instance = new Singleton();
        }
        return instance;
    }
    public void doSomething(){
        // Do something ...
    }
}

懒汉式饿汉式的最大区别就是将单例的初始化操作,延迟到需要的时候才进行,这样做在某些场合中有很大用处。比如某个单例用的次数不是很多,但是这个单例提供的功能又非常复杂,而且加载和初始化要消耗大量的资源,这个时候使用懒汉式就是非常不错的选择。

多线程下的单例模式

上面介绍了一些单例模式的基本应用方法,但是上面所说的那些使用方式都是有一个隐含的前提,那就是他们都是应用在单线程条件下,一旦换成了多线程就有出错的风险。
如果在多线程的情况下,饿汉式不会出现问题,因为JVM只会加载一次单利类,但是懒汉式可能就会出现重复创建单利对象的问题。为什么会有这样的问题呢?因为懒汉式在创建单例时是 线程不安全的,多个线程可能会并发调用他的newInstance方法导致多个线程可能会创建多份相同的单例出来。

那有没有办法,使饿汉式的单利模式也是线程安全的呢?答案肯定是有的,大家通常会使用加同步锁的方式去实现,但是这样实现起来比较麻烦。那么有没有更好的实现方式呢?能问这个问题那必须是有的,否则就得打脸了。 我们可以利用JVM的类加载机制去实现。在很多情况下JVM已经为我们提供了同步控制,比如:

  • static{}区块中初始化的数据
  • 访问final字段时
  • ...
  • 等等

因为在JVM进行类加载的时候他会保证数据是同步的,我们可以这样实现:

采用内部类,在这个内部类里面去创建对象实例。这样的话,只要应用中不使用内部类 JVM 就不会去加载这个单例类,也就不会创建单例对象,从而实现懒汉式的延迟加载和线程安全。

实现代码如下:

public class Singleton{
    //内部类,在装载该内部类时才会去创建单利对象
    private static class SingletonHolder{
        public static Singleton instance = new Singleton();
    }

    private Singleton(){}

    public static Singleton newInstance(){
        return SingletonHolder.instance;
    }

    public void doSomething(){
        //do something
    }
}

这样实现出来的单例类就是线程安全的,麻麻再也不用担心我的单例不是单例了。

使用枚举实现单例模式

除了上述的单例模式的实现方式外,我们还可以通过枚举类来实现单利模式,这也是Effective Java中推荐的方式。

使用枚举类型实现单例模式如下:

public enum Singleton{
    //定义一个枚举的元素,它就是Singleton的一个实例
    instance;

    public void doSomething(){
        // do something ...
    }    
}

用枚举实现是不是更简单呢?枚举方式实现的单例模式也是线程安全的,所以大家不用担心多线程问题,可以大胆去用。

以上就是单例模式的使用,现在完全可以说,你真的会用单例模式了。

相关文章

  • 你真的会用单例模式吗

    转载请注明出处:http://tedyin.me/2016/03/13/singlton-pattern/ 今天给...

  • 你真的会用单例模式吗?

    一、简介: 单例模式:确保一个类只有一个实例,并提供一个全局访问点. 单例模式是所有设计模式中最简单的一个,也是大...

  • 单例模式(Java内部类加载顺序)

    你真的会写单例模式吗——Java实现Android设计模式源码解析之单例模式深度分析 Java 的枚举类型:枚举的...

  • 你真的会写单例吗?

    你真的会写单例吗? 摘录来源 单例的正确姿势 Java单例模式可能是最简单也是最常用的设计模式,一个完美的单例需要...

  • 单例模式的优化方案

    参考:你真的会写单例吗? 单例模式最常见的就是懒汉式加载: 例: 当调用getInstance方法时才去创建对象,...

  • Java单例模式

    转载: 你真的会写单例模式吗-------Java实现 单例模式可能是代码最少的模式了,但是少不一定意味着简单,想...

  • 简记Android源码设计模式——第一篇

    单例模式 介绍 单例模式可谓是都会用到的一个设计模式。单例顾名思义只有一个实例。就像规定任何时候你只能有一个老婆或...

  • 单例模式

    在我们的开发中,有很多地方会用到单例模式,那么会写基本的单例模式使我们基本的素养,如果说现在不会手写单例模式的,那...

  • 羊皮书APP(Android版)开发系列(二十二)10分钟秒懂单

    单例模式在实际开发过程中经常会用到,我们有必要充分的理解单例模式。单例模式有多种写法,分为懒汉式、饿汉式、双重锁等...

  • Go单例模式

    单例模式回顾 以前在做java的时候,经常会用到设计模式,如单例模式、工厂模式、观察者模式等。其实设计模式和语言无...

网友评论

    本文标题:你真的会用单例模式吗

    本文链接:https://www.haomeiwen.com/subject/zstflttx.html