单例的实现
1.单线程下的Lazy实现
public class Main {
private static Main instance = null;
private Main() {}
public static Main getInstance() {
if(null == instance) instance = new Main();
return instance;
}
}
2.针对1的多线程阻塞实现
就是改进了check-then-act的原子性问题
public class Main {
private static Main instance = null;
private Main() {}
public static Main getInstance() {
synchronized(Main.class) {
if(null == instance) instance = new Main();
}
return instance;
}
}
3.错误的双重加锁
public class Main {
private static Main instance = null;
private Main() {}
public static Main getInstance() {
if(null == instance) synchronized(Main.class) {
if(null == instance) instance = new Main(); // 问题出现在初始化
}
return instance;
}
}
注意可见性是正确的,错误在于初始化的重排序
上一篇文章已经写了3个步骤,一个线程在判断第一个if的时候可能另一个线程执行到第二个步骤就写入引用了,这时返回的是默认值
4.正确的双重加锁
既然重排序有问题那当然要volatile
public class Main {
private static volatile Main instance = null;
private Main() {}
public static Main getInstance() {
if(null == instance) synchronized(Main.class) {
if(null == instance) instance = new Main();
}
return instance;
}
}
5.静态内部类
利用class文件对于内部类的特性,实现上够简单
public class Main {
private static class InstanceHolder {
final static Main INSTANCE = new Main();
}
public static Main getInstance() {
return InstanceHolder.INSTANCE;
}
}
6.枚举类
仅访问Singleton本身不会使Singleton.INSTANCE初始化
public enum Singleton {
INSTANCE;
Singleton() {}
public void doSomething() {}
}
public class Main {
public static void main() {
new Thread() {
public void run() {
Singleton.INSTANCE.doSomething();
}
}.start();
}
}
懒汉?饿汉?
补充一下奇怪的术语:懒汉式、饿汉式
其中懒汉式就是带Lazy加载的意思,比如1、2
而饿汉式我并不太清楚字面上的意思。。应该是指内存宽裕吧。。就是static直接返回的那种,显然不如静态内部类
public class Main {
private static Main instance = new Main();
private Main() {}
public static Main getInstance() { return instance; }
}
破坏单例模式
1.除了enum和静态内部类,其它都可以被newInstance()拿到手
改进方法就是在构造方法创建保护null的判断
2.还有一种反序列化的破坏方式(如果你的单例需要序列化)。。
解决方法是重写readResolve()
方法,使得它在方法内直接返回instance