单例模式:一个类只能有一个实例
首先,一个类要想只有一个实例,构造函数必须是私有的(如果是共有的,那就谁都可以实例化了)。其次因为构造函数是私有的,如果想外部调用这个类的话,必须要存在一个公有的静态方法。还有为了保证公有的方法返回实例的过程中实例的唯一性,这个实例应该是静态的。
总结一下就是,单例模式有以下三个要素:
单例模式根据实例化对象时机的不同分为两种:一种是饿汉式单例,一种是懒汉式单例。饿汉式单例在单例类被加载时候,就实例化一个对象交给自己的引用;而懒汉式在调用取得实例方法的时候才会实例化对象。代码如下:
接下来来看几个网上的小例子
饿汉模式
饿汉模式—例子一:
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