单例模式的一点研究

单例模式(singleton)是常用的设计模式,它只允许一个类被实例化1次。实现机制,定义或声明一个本类类型的静态域用来保存本类的实例,将构造方法私有化,提供一个公有的静态方法用来返回本类的实例。

单例模式有多重实现方法。

例1,饿汉式

/**
 * 单线程下饿汉单例模式
 */
package pattern.singleton.singleThread.hunger;

public class HungerSingleton {

    private static HungerSingleton instance = new HungerSingleton();

    private HungerSingleton() {
        System.out.println("正在实例化HungerSingleton");
    }

    public static HungerSingleton getInstance() {
        return instance;
    }

    public static void print() {
        System.out.println("aaa");
    }

}

此例中HungerSingleton保存了一个本类实例的引用。并提供一个静态方法返回此实例getInstance()。

主函数:

/**
 * 单例模式实验
 */
package pattern.singleton;

import pattern.singleton.singleThread.hunger.HungerSingleton;

public class SingletonTest {

    public static void main(String[] args) {
        HungerSingleton singleton1;
        System.out.println("声明了一个HungerSingleton");
        HungerSingleton.print();
        for (int i = 0; i < 10; i++) {
            singleton1 = HungerSingleton.getInstance();
            System.out.println("singleton1--" + i + " 是 " + singleton1);
        }
    }
}

运行结果:

------------------------------------Console--------------------------------------

声明了一个HungerSingleton
正在实例化HungerSingleton
aaa
singleton1--0 是 pattern.singleton.singleThread.hunger.HungerSingleton@4f1d0d
singleton1--1 是 pattern.singleton.singleThread.hunger.HungerSingleton@4f1d0d
singleton1--2 是 pattern.singleton.singleThread.hunger.HungerSingleton@4f1d0d
singleton1--3 是 pattern.singleton.singleThread.hunger.HungerSingleton@4f1d0d
singleton1--4 是 pattern.singleton.singleThread.hunger.HungerSingleton@4f1d0d
singleton1--5 是 pattern.singleton.singleThread.hunger.HungerSingleton@4f1d0d
singleton1--6 是 pattern.singleton.singleThread.hunger.HungerSingleton@4f1d0d
singleton1--7 是 pattern.singleton.singleThread.hunger.HungerSingleton@4f1d0d
singleton1--8 是 pattern.singleton.singleThread.hunger.HungerSingleton@4f1d0d
singleton1--9 是 pattern.singleton.singleThread.hunger.HungerSingleton@4f1d0d

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

从结果上可以看到HungerSingleton的构造方法只被调用了一次。for循环中得到的所有的HungerSingleton的实例的地址都是相同的,也就是HungerSingleton只有一个实例。

#################################################

例2:懒汉式

/**
 * 单线程下懒汉单例模式
 */
package pattern.singleton.singleThread.lazy;

public class LazySingleton {

    private static LazySingleton instance = null;

    private LazySingleton() {
        System.out.println("正在实例化LazySingleton");
    }

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

    public static void print() {
        System.out.println("aaa");
    }

}

此例中静态域instance的初始值是null。在调用getInstance()中判断instance是否引用一个实例。否则构造一个实例。这样可以保证类在需要实例化时才构造这个实例。而不是在加载这个类时就实例化这个类。

主函数:

/**
 * 单例模式实验
 */
package pattern.singleton;

import pattern.singleton.singleThread.lazy.LazySingleton;

public class SingletonTest {

    public static void main(String[] args) {
        LazySingleton singleton1;
        System.out.println("声明了一个LazySingleton");
        LazySingleton.print();
        for (int i = 0; i < 10; i++) {
            singleton1 = LazySingleton.getInstance();
            System.out.println("singleton1--" + i + " 是 " + singleton1);
        }
    }
}

运行结果:

------------------------------------Console--------------------------------------

声明了一个LazySingleton
aaa
正在实例化LazySingleton
singleton1--0 是 pattern.singleton.singleThread.lazy.LazySingleton@4f1d0d
singleton1--1 是 pattern.singleton.singleThread.lazy.LazySingleton@4f1d0d
singleton1--2 是 pattern.singleton.singleThread.lazy.LazySingleton@4f1d0d
singleton1--3 是 pattern.singleton.singleThread.lazy.LazySingleton@4f1d0d
singleton1--4 是 pattern.singleton.singleThread.lazy.LazySingleton@4f1d0d
singleton1--5 是 pattern.singleton.singleThread.lazy.LazySingleton@4f1d0d
singleton1--6 是 pattern.singleton.singleThread.lazy.LazySingleton@4f1d0d
singleton1--7 是 pattern.singleton.singleThread.lazy.LazySingleton@4f1d0d
singleton1--8 是 pattern.singleton.singleThread.lazy.LazySingleton@4f1d0d
singleton1--9 是 pattern.singleton.singleThread.lazy.LazySingleton@4f1d0d

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

跟例1比较,可以看出在调用静态方法print()时。LazySingleton类并没有构造实例,而是在for循环中第一次构造。并且仍能保证单实例。

#################################################

多线程下的单例问题

改造一下例1:

/**
 * 多线程下饿汉单例
 */
package pattern.singleton.multiThread.hunger;

public class HungerSingletonT {

    private static HungerSingletonT instance = new HungerSingletonT();

    private HungerSingletonT() {
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("正在实例化HungerSingletonT");
    }

    public static HungerSingletonT getInstance() {
        return instance;
    }

    public static void print(String threadName) {
        System.out.println(threadName + " aaa");
    }

}

在构造方法中增加一个睡眠。

测试类:

package pattern.singleton.multiThread;

import pattern.singleton.multiThread.hunger.HungerSingletonT;

public class MultiThreadTest {

    public static void main(String[] args) {
        SingletonUser s1 = new SingletonUser("s1");
        SingletonUser s2 = new SingletonUser("s2");
    }

}

class SingletonUser implements Runnable {

    private String threadName;

    public SingletonUser(String threadName) {
        this.threadName = threadName;
        Thread t = new Thread(this, threadName);
        t.start();
    }

    @Override
    public void run() {
        HungerSingletonT singleton;
        System.out.println("线程 " + threadName + " 声明了一个singleton");
        HungerSingletonT.print(threadName);
        for (int i = 0; i < 10; i++) {
            singleton = HungerSingletonT.getInstance();
            System.out.println(threadName + " : singleton--" + i + " 是 " + singleton);
        }
    }

}

运行结果:

------------------------------------Console--------------------------------------

线程 s2 声明了一个singleton
线程 s1 声明了一个singleton
正在实例化HungerSingletonT
s2 aaa
s2 : singleton--0 是 pattern.singleton.multiThread.hunger.HungerSingletonT@10b30a7
s2 : singleton--1 是 pattern.singleton.multiThread.hunger.HungerSingletonT@10b30a7
s2 : singleton--2 是 pattern.singleton.multiThread.hunger.HungerSingletonT@10b30a7
s2 : singleton--3 是 pattern.singleton.multiThread.hunger.HungerSingletonT@10b30a7
s2 : singleton--4 是 pattern.singleton.multiThread.hunger.HungerSingletonT@10b30a7
s2 : singleton--5 是 pattern.singleton.multiThread.hunger.HungerSingletonT@10b30a7
s2 : singleton--6 是 pattern.singleton.multiThread.hunger.HungerSingletonT@10b30a7
s2 : singleton--7 是 pattern.singleton.multiThread.hunger.HungerSingletonT@10b30a7
s1 aaa
s1 : singleton--0 是 pattern.singleton.multiThread.hunger.HungerSingletonT@10b30a7
s2 : singleton--8 是 pattern.singleton.multiThread.hunger.HungerSingletonT@10b30a7
s2 : singleton--9 是 pattern.singleton.multiThread.hunger.HungerSingletonT@10b30a7
s1 : singleton--1 是 pattern.singleton.multiThread.hunger.HungerSingletonT@10b30a7
s1 : singleton--2 是 pattern.singleton.multiThread.hunger.HungerSingletonT@10b30a7
s1 : singleton--3 是 pattern.singleton.multiThread.hunger.HungerSingletonT@10b30a7
s1 : singleton--4 是 pattern.singleton.multiThread.hunger.HungerSingletonT@10b30a7
s1 : singleton--5 是 pattern.singleton.multiThread.hunger.HungerSingletonT@10b30a7
s1 : singleton--6 是 pattern.singleton.multiThread.hunger.HungerSingletonT@10b30a7
s1 : singleton--7 是 pattern.singleton.multiThread.hunger.HungerSingletonT@10b30a7
s1 : singleton--8 是 pattern.singleton.multiThread.hunger.HungerSingletonT@10b30a7
s1 : singleton--9 是 pattern.singleton.multiThread.hunger.HungerSingletonT@10b30a7

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

JVM的运行机制可以保证一个类在被加载的过程中是线程互斥的。饿汉的先行加载使得HungerSingletonT在第一次加载时实例化已完成。所以饿汉式单例是线程安全的。

#################################################

多线程下懒汉式单例问题。

    public static LazySingleton getInstance() {
        if (instance == null) {
            instance = new LazySingleton();
        }
        return instance;
    }
设有线程t1和t2,t1在判断完instance==null之后进入到实例化LazySingleton,此时t2也执行到这里,判断instance==null。由于t1的实例化尚未完成,此时instance==null仍为true。所以t2顺利进行new LazySingleton()。于是LazySingleton被实例化了两次。所以懒汉式单例在多线程下是不安全的。

如下例所示:

/**
 * 多线程下的懒汉式单例
 */
package pattern.singleton.multiThread.lazy;

public class LazySingletonT {

    private static LazySingletonT instance = null;

    private LazySingletonT(String str) {
        System.out.println(str + " 正在实例化LazySingletonT");
    }

    public static LazySingletonT getInstance(String str) {
        if (instance == null) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            instance = new LazySingletonT(str);
        }
        return instance;
    }

    public static void print(String str) {
        System.out.println(str + " aaa");
    }

}

测试类:

package pattern.singleton.multiThread;

import pattern.singleton.multiThread.lazy.LazySingletonT;

public class MultiThreadTest {

    public static void main(String[] args) {
        SingletonUser s1 = new SingletonUser("s1");
        SingletonUser s2 = new SingletonUser("s2");
    }

}

class SingletonUser implements Runnable {

    private String threadName;

    public SingletonUser(String threadName) {
        this.threadName = threadName;
        Thread t = new Thread(this, threadName);
        t.start();
    }

    @Override
    public void run() {
        LazySingletonT singleton;
        System.out.println("线程 " + threadName + " 声明了一个singleton");
        LazySingletonT.print(threadName);
        for (int i = 0; i < 10; i++) {
            singleton = LazySingletonT.getInstance(threadName);
            System.out.println(threadName + " : singleton--" + i + " 是 " + singleton);
        }
    }

}

运行结果:

------------------------------------Console--------------------------------------

线程 s2 声明了一个singleton
线程 s1 声明了一个singleton
s2 aaa
s1 aaa
s1 正在实例化LazySingletonT
s1 : singleton--0 是 pattern.singleton.multiThread.lazy.LazySingletonT@10b30a7
s1 : singleton--1 是 pattern.singleton.multiThread.lazy.LazySingletonT@10b30a7
s2 正在实例化LazySingletonT
s2 : singleton--0 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s1 : singleton--2 是 pattern.singleton.multiThread.lazy.LazySingletonT@10b30a7
s1 : singleton--3 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s2 : singleton--1 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s2 : singleton--2 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s2 : singleton--3 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s2 : singleton--4 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s2 : singleton--5 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s2 : singleton--6 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s2 : singleton--7 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s2 : singleton--8 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s2 : singleton--9 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s1 : singleton--4 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s1 : singleton--5 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s1 : singleton--6 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s1 : singleton--7 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s1 : singleton--8 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s1 : singleton--9 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb

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

不难看出s1和s2分别实例化了一次LazySingletonT。

多线程下如何实现单例模式的延迟加载。我们先来改进一下懒汉式单例,给他增加一个锁synchronized。

例3:

public static synchronized LazySingletonT getInstance(String str) {
        if (instance == null) {
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            instance = new LazySingletonT(str);
        }
        return instance;
    }

运行结果:

------------------------------------Console--------------------------------------

线程 s2 声明了一个singleton
线程 s1 声明了一个singleton
s2 aaa
s1 aaa
s2 正在实例化LazySingletonT
s2 : singleton--0 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s2 : singleton--1 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s2 : singleton--2 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s2 : singleton--3 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s2 : singleton--4 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s2 : singleton--5 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s2 : singleton--6 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s2 : singleton--7 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s2 : singleton--8 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s2 : singleton--9 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s1 : singleton--0 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s1 : singleton--1 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s1 : singleton--2 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s1 : singleton--3 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s1 : singleton--4 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s1 : singleton--5 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s1 : singleton--6 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s1 : singleton--7 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s1 : singleton--8 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb
s1 : singleton--9 是 pattern.singleton.multiThread.lazy.LazySingletonT@1a758cb

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

看样子问题得到解决了。但新的问题是每一次调用getInstance都必须得到LazySingletonT的锁才行。而事实上只有第一次实例化时才需要锁住LazySingletonT,其他的时候getInstance只是返回已存在的LazySingletonT实例的引用,没必要获得锁。此例虽然解决了单例的互斥问题,但却影响了性能。

#################################################

整个方法需要获得对象锁会影响性能,那么只把实例化的部分放到同步块中会如何呢。

例4:双检锁

/**
 * 双检锁单例模式
 */
package pattern.singleton.multiThread.lazy;

public class DCLSingleton {

    private static DCLSingleton instance = null;

    private DCLSingleton(String str) {
        System.out.println("线程 " + str + " 正在实例化DCLSingleton");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    public static void print(String str) {
        System.out.println(str + " aaa");
    }

    public static DCLSingleton getInstance(String str) {
        if (instance == null) {
            synchronized (DCLSingleton.class) {
                if (instance == null) {
                    instance = new DCLSingleton(str);
                }
            }
        }
        return instance;
    }

}

这里很多帖子这样写synchronized(instance),这会抛出空指针异常(NullPointerException)。因为此时instance是空。线程无法获得对象锁。

测试类:

package pattern.singleton.multiThread;

import pattern.singleton.multiThread.lazy.DCLSingleton;

public class MultiThreadTest {

    public static void main(String[] args) {
        SingletonUser s1 = new SingletonUser("s1");
        SingletonUser s2 = new SingletonUser("s2");
    }

}

class SingletonUser implements Runnable {

    private String threadName;

    public SingletonUser(String threadName) {
        this.threadName = threadName;
        Thread t = new Thread(this, threadName);
        t.start();
    }

    @Override
    public void run() {
        DCLSingleton singleton;
        System.out.println("线程 " + threadName + " 声明了一个singleton");
        DCLSingleton.print(threadName);
        for (int i = 0; i < 10; i++) {
            singleton = DCLSingleton.getInstance(threadName);
            System.out.println(threadName + " : singleton--" + i + " 是 " + singleton);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

运行结果:

------------------------------------Console--------------------------------------

线程 s1 声明了一个singleton
线程 s2 声明了一个singleton
s1 aaa
线程 s1 正在实例化DCLSingleton
s2 aaa
s2 : singleton--0 是 pattern.singleton.multiThread.lazy.DCLSingleton@10b30a7
s1 : singleton--0 是 pattern.singleton.multiThread.lazy.DCLSingleton@10b30a7
s2 : singleton--1 是 pattern.singleton.multiThread.lazy.DCLSingleton@10b30a7
s1 : singleton--1 是 pattern.singleton.multiThread.lazy.DCLSingleton@10b30a7
s2 : singleton--2 是 pattern.singleton.multiThread.lazy.DCLSingleton@10b30a7
s1 : singleton--2 是 pattern.singleton.multiThread.lazy.DCLSingleton@10b30a7
s2 : singleton--3 是 pattern.singleton.multiThread.lazy.DCLSingleton@10b30a7
s1 : singleton--3 是 pattern.singleton.multiThread.lazy.DCLSingleton@10b30a7
s2 : singleton--4 是 pattern.singleton.multiThread.lazy.DCLSingleton@10b30a7
s1 : singleton--4 是 pattern.singleton.multiThread.lazy.DCLSingleton@10b30a7
s1 : singleton--5 是 pattern.singleton.multiThread.lazy.DCLSingleton@10b30a7
s2 : singleton--5 是 pattern.singleton.multiThread.lazy.DCLSingleton@10b30a7
s2 : singleton--6 是 pattern.singleton.multiThread.lazy.DCLSingleton@10b30a7
s1 : singleton--6 是 pattern.singleton.multiThread.lazy.DCLSingleton@10b30a7
s2 : singleton--7 是 pattern.singleton.multiThread.lazy.DCLSingleton@10b30a7
s1 : singleton--7 是 pattern.singleton.multiThread.lazy.DCLSingleton@10b30a7
s2 : singleton--8 是 pattern.singleton.multiThread.lazy.DCLSingleton@10b30a7
s1 : singleton--8 是 pattern.singleton.multiThread.lazy.DCLSingleton@10b30a7
s2 : singleton--9 是 pattern.singleton.multiThread.lazy.DCLSingleton@10b30a7
s1 : singleton--9 是 pattern.singleton.multiThread.lazy.DCLSingleton@10b30a7

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

s1,s2两个线程。s1第一次判断instance==null为true,获得对象锁。再次判断instance==null仍为true,开始实例化DCLSingleton。此时s2第一次判断instance==null,由于instance尚未实例化完成,结果仍是true,s2等待对象锁。直到线程s1执行实例化完成释放锁,此时instance不再是空。JVM不保证new语句和赋值语句的执行顺序,但都在同步块中,JVM可以保证这些语句都执行完毕才释放锁。所以,当s2获得对象锁时进行第二次判断instance==null,此时的结果为false。s2不再实例化DCLSingleton。双检锁机制可以实现单例模式。

#################################################

双检锁经过了多次判断,而且仍然有等待的时间。事实上饿汉式已经提供了一个互斥问题的解决方法。就是利用JVM本身的对于类加载过程是互斥的机制。将问题交给虚拟机来优化,提高性能。所要解决的就是延迟加载的问题。就是instance=new Singleton()的new操作只有在需要时才执行。可以把它放在一个类里,这个类在第一次加载时才会执行new操作。内部类可以胜任这个工作。

例5:

package pattern.singleton.multiThread.lazy;

public class ICSingleton {

    private ICSingleton() {
        System.out.println("正在实例化ICSingleton");
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    private static class InnerHandle {
        private static ICSingleton instance = new ICSingleton();
    }

    public static ICSingleton getInstance() {
        return InnerHandle.instance;
    }

    public static void print(String str) {
        System.out.println(str + " aaa");
    }

}

测试类:

package pattern.singleton.multiThread;

import pattern.singleton.multiThread.lazy.ICSingleton;

public class MultiThreadTest {

    public static void main(String[] args) {
        SingletonUser s1 = new SingletonUser("s1");
        SingletonUser s2 = new SingletonUser("s2");
    }

}

class SingletonUser implements Runnable {

    private String threadName;

    public SingletonUser(String threadName) {
        this.threadName = threadName;
        Thread t = new Thread(this, threadName);
        t.start();
    }

    @Override
    public void run() {
        ICSingleton singleton;
        System.out.println("线程 " + threadName + " 声明了一个singleton");
        ICSingleton.print(threadName);
        for (int i = 0; i < 10; i++) {
            singleton = ICSingleton.getInstance();
            System.out.println(threadName + " : singleton--" + i + " 是 " + singleton);
            try {
                Thread.sleep(100);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }

}

运行结果:

------------------------------------Console--------------------------------------

线程 s1 声明了一个singleton
线程 s2 声明了一个singleton
s1 aaa
正在实例化ICSingleton
s2 aaa
s1 : singleton--0 是 pattern.singleton.multiThread.lazy.ICSingleton@10b30a7
s2 : singleton--0 是 pattern.singleton.multiThread.lazy.ICSingleton@10b30a7
s1 : singleton--1 是 pattern.singleton.multiThread.lazy.ICSingleton@10b30a7
s2 : singleton--1 是 pattern.singleton.multiThread.lazy.ICSingleton@10b30a7
s1 : singleton--2 是 pattern.singleton.multiThread.lazy.ICSingleton@10b30a7
s2 : singleton--2 是 pattern.singleton.multiThread.lazy.ICSingleton@10b30a7
s2 : singleton--3 是 pattern.singleton.multiThread.lazy.ICSingleton@10b30a7
s1 : singleton--3 是 pattern.singleton.multiThread.lazy.ICSingleton@10b30a7
s2 : singleton--4 是 pattern.singleton.multiThread.lazy.ICSingleton@10b30a7
s1 : singleton--4 是 pattern.singleton.multiThread.lazy.ICSingleton@10b30a7
s2 : singleton--5 是 pattern.singleton.multiThread.lazy.ICSingleton@10b30a7
s1 : singleton--5 是 pattern.singleton.multiThread.lazy.ICSingleton@10b30a7
s1 : singleton--6 是 pattern.singleton.multiThread.lazy.ICSingleton@10b30a7
s2 : singleton--6 是 pattern.singleton.multiThread.lazy.ICSingleton@10b30a7
s2 : singleton--7 是 pattern.singleton.multiThread.lazy.ICSingleton@10b30a7
s1 : singleton--7 是 pattern.singleton.multiThread.lazy.ICSingleton@10b30a7
s2 : singleton--8 是 pattern.singleton.multiThread.lazy.ICSingleton@10b30a7
s1 : singleton--8 是 pattern.singleton.multiThread.lazy.ICSingleton@10b30a7
s2 : singleton--9 是 pattern.singleton.multiThread.lazy.ICSingleton@10b30a7
s1 : singleton--9 是 pattern.singleton.multiThread.lazy.ICSingleton@10b30a7

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

把instance放到一个内部类中。instance不会在ICSingleton加载时初始化。直到调用getInstance方法时,加载内部类InnerHandle才会初始化instance。类在加载时是线程互斥的。这样既保证了ICSingleton的单实例也可以实现延迟加载。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值