单例模式是面试时常考的一个设计模式,面试官常常要求面试者实现一个单例模式。那么,一个面试者的实现可以分为三个层次:0层,写不出来;1层,单线程下的单例模式;2层:用double-checked locking实现的单例模式;3层,用内部类实现的单例模式。下面分别描述。
1,单线程下的单例模式
只要知道单例模式的意义--
“
单例模式是一种常用的软件设计模式。在它的核心结构中只包含一个被称为单例类的特殊类。通过单例模式可以保证系统中一个类只有一个实例而且该实例易于外界访问,从而方便对实例个数的控制并节约系统资源。如果希望在系统中某个类的对象只能存在一个,单例模式是最好的解决方案。--百度百科
”
单线程下实现如下:
class Singleton1{ //(2)静态实例 private static Singleton1 instance; //(3)提供给外部接口 public static Singleton1 getInstance(){ if(instance==null){ instance=new Singleton1(); } return instance; } //(1),private的构造函数 private Singleton1(){ } public void amethod(){ } }
2,多线程下的单例模式
上面的代码在单线程下没问题,但是在多线程下就有问题了。比如A和B两个线程同时调用getInstance方法,A执行完了nstance==null,但是时间片被B抢到,此时B执行到instance==null,条件为true,B创建instance,接着轮到了A,A继续执行,那么第二个instance被创建出来了。为了避免这一现象,必须采取同步措施,这就是所谓的double-checed lock:
class Singleton2{ private static Singleton2 instance; public static Singleton2 getInstance(){ if(instance==null){ synchronized(Singleton2.class){ if(instance==null){ instance=new Singleton2(); } } } return instance; } }
3, 通过内部类实现单例模式。
原理就是JVM内部机制能够保证当一个类被加载的时候,这个类的加载过程是互斥的
public class Singleton{ private Singleton(){ } private static class SingletonContainer{ private static Singleton instance = new Singleton(); } public static Singleton getInstance(){ return SingletonContainer.instance; } }
这样在第一次调用getInstance的时候导致SingletonContainer类的被加载和初始化,这个过程是互斥的,因此不存在instance会被创建多次的情况。