单例模式:一个类只能有一个实例
首先,一个类要想只有一个实例,构造函数必须是私有的(如果是共有的,那就谁都可以实例化了)。其次因为构造函数是私有的,如果想外部调用这个类的话,必须要存在一个公有的静态方法。还有为了保证公有的方法返回实例的过程中实例的唯一性,这个实例应该是静态的。
总结一下就是,单例模式有以下三个要素:
单例模式根据实例化对象时机的不同分为两种:一种是饿汉式单例,一种是懒汉式单例。饿汉式单例在单例类被加载时候,就实例化一个对象交给自己的引用;而懒汉式在调用取得实例方法的时候才会实例化对象。代码如下:
接下来来看几个网上的小例子
饿汉模式
饿汉模式—例子一:
public class Singleton { private static Singleton singleton = new Singleton(); private Singleton(){} public static Singleton getInstance(){ return singleton; } }
懒汉模式—例子一:
public class LazyUnsafeSingleton { private volatile static LazyUnsafeSingleton instance; private LazyUnsafeSingleton() { } public static LazyUnsafeSingleton getInstance() { if (null == instance) { instance = new LazyUnsafeSingleton(); } return instance; } }
例子一很显然在多线程下操作时不行的。当多个线程同时进入静态方法时就可能会出现多个实例。针对此修改得到例子二
public class LazyMethodSynSingleton { private static LazyMethodSynSingleton instance; private LazyMethodSynSingleton() { Logger.getGlobal().info("LazyMethodSynSingleton.LazyMethodSynSingleton()"); } public static synchronized LazyMethodSynSingleton getInstance() { if (null == instance) { instance = new LazyMethodSynSingleton(); } return instance; } }例子二采用方法同步,当执行静态方法的时候把这个操作定义为原子操作,来防止多线程调用,来实现一个实例。
懒汉模式—例子三:
采用方法同步一个不好的地方就是阻塞的时间太多了,为此将同步操作定义在方法里面,进行双重校验,只有当实例为空的时候执行同步,并且为了为了防止在外层校验的时候其他现成的干扰,内层同步部分又进行一次校验。
public class LazyDoubleCheckSingleton { private volatile static LazyDoubleCheckSingleton instance; private LazyDoubleCheckSingleton() { Logger.getGlobal().info("LazyDoubleCheckSingleton.LazyDoubleCheckSingleton()"); } public static LazyDoubleCheckSingleton getInstance() { if (null == instance) { synchronized (LazyDoubleCheckSingleton.class) { if (null == instance) { instance = new LazyDoubleCheckSingleton(); } } } return instance; } }
例子三可以达到想要的效果,但是有点繁琐,利用JVM类加载机制,可以对例子三进行优化,得到例子四。
public class LazyHolderSingleton { private static class InstanceHolder { private static final LazyHolderSingleton INSTANCE = new LazyHolderSingleton(); } private LazyHolderSingleton() { Logger.getGlobal().info("LazyHolderSingleton.LazyHOlderSingleton()"); } public static LazyHolderSingleton getInstance() { return InstanceHolder.INSTANCE; } }
原文地址:http://blog.csdn.net/zhangzhengyi03539/article/details/45914153