单例模式
1. 单例模式(Singleton)保证一个类仅有一个实例,并提供一个访问它的全局访问点。
2. 通常,我们可以让一个全局变量使得一个对象被访问,但它不能防止你实例化多个对象,一个最好的办法就是,让类自身负责保存它的唯一实例。这个类可以保证没有其他实例可以被创建,而且它可以提供一个访问该实例的方法。
3. Singleton类,定义一个GetInstance操作,允许客户访问它的唯一实例。GetInstance是一个静态方法,主要负责创建自己的唯一实例。
4. 单例模式是对唯一实例的受控访问。
5. 单例类和实用类(Math类)的区别:
6. 为了保证多线程的时候也不创建多个实例,可以先使用lock来锁住GetInstace方法。
7. 双重锁定(double-check-locking):不让线程每次都加锁,而是用if判断,在实例未被创建的时候再加锁处理,同时也能保证多线程的安全。
8. 饿汉式单例模式:静态初始化的方式是在自己被加载的时候就将自己实例化了。
9. 懒汉式单例模式:在第一次被引用时才将自己实例化。
10. 饿汉式:类一加载就实例化的对象,所以要提前占用系统资源。
11. 懒汉式:面临多线程访问的安全问题,需要双重锁定处理
1、懒汉式经典写法:
public class Singleton {
private static Singleton instance;
private Singleton (){}
public static Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
}
public static synchronized Singleton getInstance() {
if (instance == null) {
instance = new Singleton();
}
return instance;
}
3、懒汉式,线程安全写法,双重检验锁模式(double checked locking pattern)
双重检验锁使用原因:对于instance存在的情况,直接返回没有问题。但是当instance为null,并且同时有两个线程调用getInstance()方法时,它们都可以通过第一重instance=null的判断,然后由于lock机制,只有一个能够进入,另一个在外面排队,此时如果没有第二个instance=null的判断,后一个进入的线程还是可以继续创建实例。
public static Singleton getSingleton() {
if (instance == null) { //Single Checked
synchronized (Singleton.class) {
if (instance == null) { //Double Checked
instance = new Singleton();
}
}
}
return instance ;
}
5、懒汉式,静态内部类写法。
使用JVM机制保证线程安全,因为singletoHolder是私有的,除了get方法不能访问。
public class Singleton {
private static class SingletonHolder {
private static final Singleton INSTANCE = new Singleton();
}
private Singleton (){}
public static final Singleton getInstance() {
return SingletonHolder.INSTANCE;
}
}
4、饿汉式,经典写法(static final)
在第一次加载类到内存中就会初始化,创建实例本身就是安全的。
public class Singleton{
//类加载时就初始化
private static final Singleton instance = new Singleton();
private Singleton(){}
public static Singleton getInstance(){
return instance;
}
}
但是饿汉式并不是完美的,如果singleton实例是依赖参数或者是配置文件的,不能在加载时就初始化,这样的场景是不能使用的。
参考:【http://wuchong.me/blog/2014/08/28/how-to-correctly-write-singleton-pattern/】