《剑指Offer》面试题二之实现Singleton

来源:互联网 发布:php curl 下载文件 编辑:程序博客网 时间:2024/06/06 09:45

题目描述

设计一个类,我们只能生成该类的一个实例。

解题思路

只能生成一个实例的类是实现了Singleton(单例)模式的类型。

解题方法一

由于只能生成一个实例,我们要把构造函数设置成私有的。我们定义一个静态的实例,在需要的时候创建该实例:

package newtest1;/** * 《剑指Offer》面试题 TestSingleton.java * 作者:白芷 * 时间:2017 2/28 * */public class TestSingleton {    private TestSingleton(){}    private static TestSingleton testSingleton=null;    public static TestSingleton GetSingleton(){        if(TestSingleton.testSingleton==null){            TestSingleton.testSingleton=new TestSingleton();        }        return testSingleton;    }    public static void main(String[] args){        TestSingleton t=TestSingleton.GetSingleton();        TestSingleton t1=TestSingleton.GetSingleton();        System.out.println(t);        System.out.println(t1);    }    /**     * 输出结果:     * newtest1.TestSingleton@2a139a55     * newtest1.TestSingleton@2a139a55     * */}

由程序的输出结果我们可以知道,这俩个实例是同一个实例!

发现问题

上面的程序只能用于单线程的环境,在多线程的情况下则会出现问题!

解题方法二

考虑到多线程,我们则需要进行线程的同步以及互斥,可以写出如下的代码:

package newtest1;/** * 《剑指Offer》面试题 TestMulThreadSingleton.java * 作者:白芷 * 时间:2017 3/1 * */public class TestMulThreadSingleton {    private TestMulThreadSingleton() {    }    private static TestMulThreadSingleton testSingleton = null;    public static TestMulThreadSingleton GetTestMulThreadSingleton() {        synchronized (TestMulThreadSingleton.class) {            if (testSingleton == null) {                testSingleton = new TestMulThreadSingleton();            }        }        return testSingleton;    }}

发现问题

这种解法虽然在多线程的情况下是可行的,但是我们应该注意到:

每次得到 testSingleton 实例的时候都会试图加上一个同步锁,而加锁是一个非常耗时的操作,在没有必要的时候我们应该尽量避免

所以我们还得优化这个程序。

解题方法三

package newtest1;/** * 《剑指Offer》面试题TestFinalSingleton.java * 作者:白芷 * 时间:2017 3/1 * */public class TestFinalSingleton {    private TestFinalSingleton(){}    private static TestFinalSingleton testSingleton=null;    public static TestFinalSingleton GetSingletonInstance(){        if(testSingleton==null){            synchronized(TestFinalSingleton.class){                if(testSingleton==null){                    testSingleton=new TestFinalSingleton();                }            }        }        return testSingleton;    }}

这种方法看起来比较啰嗦,但是其有点如下:

  • 如果已经创建了实例,则直接返回
  • 如果没有创建,如果这时候多个线程同时进入,则这个时候加上同步锁,只允许一个线程进入创建实例,这时候其他线程进入时,则不会通过第二次的判断。

基本上这就是一个可行的解法了!

0 0
原创粉丝点击