java中单例模式的实现

来源:互联网 发布:head first java电子书 编辑:程序博客网 时间:2024/06/05 08:17

lazy loaded thread-safe单例模式实现

DCL (double checked locking 实现法) double checked locking ,顾名思义,就是双检查法,检查实例INSTANCE是否为null或者已经实例化了。

public class DoubleCheckedLockingSingleton {    private volatile DoubleCheckedLockingSingleton INSTANCE;// 创建一个私有的,可变的 实例    //volatile:能保证在一个线程中改变这个值,其他线程能够立即知道发生改变。    public DoubleCheckedLockingSingleton getInstance() {        if (INSTANCE == null) {            synchronized (DoubleCheckedLockingSingleton.class) {                if (INSTANCE == null)                    INSTANCE = new DoubleCheckedLockingSingleton();            }        }        return INSTANCE;    }}

注:synchronized(this)与synchronized(ClassName.class)区别

  • synchronized(this)对当前对象是同步的,所以只有一个线程可以访问每个实例,但不同的线程可以访问不同的实例。
    例如,你有很多线程和很多该类实例,但是同时每个实例对应的同步内容都可以被一个线程访问。(在任意时间点,这个类的一个实例只能被一个线程访问,但一个线程可以同时访问该类多个实例)
  • synchronized(ClassName.class)对当前对象的类(或其他类)是同步的,所以只有一个线程可以访问该类的实例。
    例如,你有很多线程和很多该类实例,但是同时只允许一个线程访问一个实例的同步内容。(在任意时间点,该类的所有实例只能有一个实例被所有线程中的一个线程访问)

lazy initialization holder class 模式实现法

package 单例模式;public class Singleton {    /**     * 类级的内部类,也就是静态的成员式内部类,该内部类的实例与外部类的实例 没有绑定关系,而且只有被调用到才会装载,从而实现了延迟加载     */    private static class SingletonHolder {        /**         * 静态初始化器,由JVM来保证线程安全         */        private static Singleton instance = new Singleton();    }    /**     * 私有化构造方法     */    private Singleton() {    }    public static Singleton getInstance() {        return SingletonHolder.instance;    }}

当getInstance方法第一次被调用的时候,它第一次读取SingletonHolder.instance,导致SingletonHolder类得到初始化;而这个类在装载并被初始化的时候,会初始化它的静态域,从而创建Singleton的实例,由于是静态的域,因此只会被虚拟机在装载类的时候初始化一次,并由虚拟机来保证它的线程安全性。这个模式的优势在于,getInstance方法并没有被同步,并且只是执行一个域的访问,因此延迟初始化并没有增加任何访问成本。

注:关于延迟初始化(lazy loaded)

“除非绝对必要,否则就不要延迟初始化”。延迟初始化是一把双刃剑,它降低了初始化类或者创建实例的开销,却增加了访问被延迟初始化的域的开销,考虑到延迟初始化的域最终需要初始化的开销以及域的访问开销,延迟初始化实际上降低了性能。


静态工厂实现法

public class Singleton {    private static final Singleton INSTATNCE = new Singleton();    private Singleton() {    }    public static Singleton getSingleton() {        return INSTATNCE;    }}

static关键字:在加载类的过程中完成变量的内存分配
final关键字:描述变量为常量,不会被改变

在类加载时就将INSTATNCE 创建好,在程序中调用的都是已经创建好的实例。

原创粉丝点击