1、饥饿模式
//饥饿模式 public final class Singleton { private static Singleton singObj = new Singleton(); private Singleton(){ } public static Singleton getSingleInstance(){ return singObj; } }
饥饿模式,每个对象在没有使用之前就已经初始化了,有点资源浪费,同时也会加重系统启动时的负担;
2、懒汉模式
//懒汉模式 public final class Singleton { private static Singleton singObj = null; private Singleton(){ } public static Singleton getSingleInstance(){ if(null == singObj ){ singObj = new Singleton(); } return singObj; } }
懒汉模式解决了上面饥饿模式的未使用就加载的问题,只有在使用时才创建,相对来说更优一些,但是问题又来了,在高并发系统中,这两种模式下创建单例对象是线程安全的吗?答案显而易见是否定的,那如何线程安全的创建单例对象呢?
3、线程安全的方式创建单例对象
public final class Singleton { private static Singleton singObj = null; private Singleton(){ } public static Synchronized Singleton getSingleInstance(){ if(null == singObj ){ singObj = new Singleton(); } return singObj; } }
在 getSingleInstance()方法上加上synchronized关键字的确可以解决线程安全的问题,但是使用synchronized关键字会阻塞线程,势必会降低系统的并发性,有没有更优雅的一种方式来实现呢?
4、优雅的支持高并发方式的单例
public class Singleton { private static class SingletonHolder { public final static Singleton instance = new Singleton(); } public static Singleton getInstance() { return SingletonHolder.instance; } }
这种方法使用内部类来做到延迟加载对象,在初始化这个内部类的时候,JLS(Java Language Sepcification)会保证这个类的线程安全。这种写法最大的美在于,完全使用了Java虚拟机的机制进行同步保证,没有一个同步的关键字。