单例模式:确保一个类只有一个实例并提供一个对它的全局访问指针
什么是线程安全?
如果你的代码所在的进程中有多个线程在同时运行,而这些线程可能会同时运行这段代码。如果每次运行结果和单线程运行的结果是一样的,而且其他的变量的值也和预期的是一样的,就是线程安全的。
或者说:一个类或者程序所提供的接口对于线程来说是原子操作,或者多个线程之间的切换不会导致该接口的执行结果存在二义性,也就是说我们不用考虑同步的问题,那就是线程安全的。
懒汉式单例
public class Singleton {
private Singleton() {}
private static Singleton single=null;
public static Singleton getInstance() {
if (single == null) {
single = new Singleton();
}
return single;
}
}
懒汉式只有在调用getInstance的时候,才回去初始化这个单例,它是线程不安全的,并发环境下很可能出现多个Singleton实例,要实现线程安全,有以下三种方式,都是对getInstance这个方法改造,保证了懒汉式单例的线程安全
在getInstance方法上加同步
public class Singleton {
private Singleton() {}
private volatile static Singleton single=null;
public static synchronized Singleton getInstance() {
if (single == null) {
single = new Singleton();
}
return single;
}
}
双重检查锁定
public class Singleton {
private Singleton() {}
private volatile static Singleton single=null;
public static Singleton getInstance() {
if (singleton == null) {
synchronized (Singleton.class) {
if (singleton == null) {
singleton = new Singleton();
}
}
}
return singleton;
}
}
静态内部类
public class Singleton {
private static class LazyHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return LazyHolder.INSTANCE;
}
}
饿汉式单例
public class Singleton {
private Singleton() {}
private static final Singleton single = new Singleton();
public static Singleton getInstance() {
return single;
}
}
饿汉式在类创建的同时就已经创建好一个静态的对象供系统使用,所以线程安全
枚举
public enum Singleton{
INSTANCE;
public void Singleton(){
}
}
这个思想直接源于Joshua Bloch的《Effective Java》(《Java高效编程指南》),不仅能避免多线程同步问题,而且还能防止反序列化重新创建新的对象