Java面试向:脑图单例模式

2018-09-21  本文已影响15人  拾识物者

单例模式,绝对是面试时被问到最多的设计模式。如果搜索网上的java单例模式,这篇文章是说得最全面和深入的:

你真的会写单例模式吗——Java实现

本文的脑图就是这篇文章的总结和精炼:百度脑图

脑图截图

单例模式概念上是很简单的:提供和限制全局唯一的对象。复杂的是现实问题和实现方法。

衡量Java单例模式的好坏有几个方面:

另外,《游戏设计模式》一书中对单例模式的剖析很有趣,作者建议你不用单例模式。为什么?最直接的一个原因是:单例模式本质上就是一个全局变量啊!中文版传送门

以下是几种实现代码,脑图上放代码看起来有些费劲。

先定义一个获取方法的main方法来进行一个简单的测试,目的是判断是否延迟加载。

public class DemoSingleton {
    public static void main(String[] args) {
        SingletonClass.getInstance();
    }
}

另一个测试,简单的测试一下是否是线程安全的,如果输出了两个构造函数的log那么肯定是不安全的。由于线程调度的不确定性,可能需要调整一下线程的数量,再多试几次。最好玩的是第三个方法中,去掉volatile关键字或者去掉一层判断,可以更好地理解为什么要写这么多代码来保证线程安全。

public class DemoSingleton {
    public static void main(String[] args) {
        for (int i = 0; i < 25; i++) {
            new Thread(new Runnable(){
                @Override
                public void run() {
                    try {
                        Thread.sleep(1000);
                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                    SingletonClass.getInstance();
                }
            }).start();
        }
    }
}
  1. 定义静态字段时直接初始化:简单;线程安全;不延迟
class SingletonClass {
    private static SingletonClass instance = new SingletonClass();
    public static SingletonClass getInstance() {
        System.out.println("getInstance()");
        return instance;
    }
    private SingletonClass() {
        System.out.println("new SingletonClass");
    }
}
// 输出
// new SingletonClass
// getInstance()
  1. 静态方法中简单判断唯一性:简单;线程不安全;延迟
class SingletonClass {
    private static SingletonClass instance;
    public static SingletonClass getInstance() {
        System.out.println("getInstance()");
        if (instance == null) {
            instance = new SingletonClass();
        }
        return instance;
    }
    private SingletonClass() {
        System.out.println("new SingletonClass");
    }
}
// 输出
// getInstance()
// new SingletonClass
  1. 静态方法中判断唯一性考虑线程安全:复杂;线程安全;延迟
class SingletonClass {
    private static volatile SingletonClass instance;
    public static SingletonClass getInstance() {
        System.out.println("getInstance()");
        if (instance == null) {
            synchronized(SingletonClass.class) {
                if (instance == null) {
                    instance = new SingletonClass();
                }
            }
        }
        return instance;
    }
    private SingletonClass() {
        System.out.println("new SingletonClass");
    }
}
// 输出
// getInstance()
// new SingletonClass
  1. 静态内部类:简单;线程安全;延迟
class SingletonClass {
    private static class SingletonHolder {
        private static volatile SingletonClass instance = new SingletonClass();
    }
    public static SingletonClass getInstance() {
        System.out.println("getInstance()");
        return SingletonHolder.instance;
    }
    private SingletonClass() {
        System.out.println("new SingletonClass");
    }
}
// 输出
// getInstance()
// new SingletonClass
  1. 枚举法:诡异;线程安全;不延迟
enum SingletonClass {
    INSTANCE;
    public static SingletonClass getInstance() {
        System.out.println("getInstance()");
        return INSTANCE;
    }
    private SingletonClass() {
        System.out.println("new SingletonClass");
    }
}
// 输出
// new SingletonClass
// getInstance()

拜拜,煮面时顺溜

参考资料
http://www.tekbroaden.com/singleton-java.html
https://gpp.tkchu.me/singleton.html

上一篇下一篇

猜你喜欢

热点阅读