单例模式,顾名思义要确保某一个类只能存在一个实例,类要自行创建自己的唯一实例,并且要像整个系统提供这个实例。
单例模式是为了避免不一致的状态,避免政出多头的现象。所以多为具有资源管理功能的类,常见的如线程池,日志,缓存等。
编写单例模式要保证:
1.单例只能有一个实例
2.单例必须自己创建自己的唯一实例
3.单例类必须给其他对象提供方法访问这唯一实例
单例模式 懒汉式
public class Singleton {
//私有的空构造方法,禁止除本类之外的访问
private Singleton(){};
//初始化一个空的实例
private static Singleton single = null;
//提供静态获取Singleton方法供其他类获取实例
public static Singleton getInstance(){
if(single == null){
this.single = new Singleton();
}
return this.single;
}
}
外部类在调用getInstance的时候才会创建单例实例,所以被称为懒汉式。
此方法没有保证线程安全问题,当多个线程同时调用getInstance方法,可能产生多个Singleton实例。
线程安全的懒汉式单例模式
1.为getInstance添加synchronized锁,此种方式虽然能保障多线程下可以正常工作,也有lazy loading。但是由于添加了synchronized锁,导致效率很慢,而且在大多数情况下是不需要进行同步的。
public class Singleton {
private Singleton(){};
private static Singleton single = null;
//添加synchronized锁
public static synchronized getInstance(){
if (this.single == null){
this.single = new Singleton();
}
return this.single;
}
}
2.添加双重校验锁,此方法为上一个的升级版,在getInstance中做了两次null检查,确保了只有第一次调用单例的时候才会做同步,这样也是线程安全的,同时避免了每次都同步的性能损耗。
public class Singleton {
private Singleton(){};
private static Singleton single = null;
//添加双重验证synchronized锁
public static getInstance(){
if (this.single == null){
synchronized(Singleton.class){
if(this.single == null){
this.single = new Singleton();
}
}
}
return this.single;
}
}
3.使用静态内部类,比较推荐。这种方式利用了calssloder机制保证初始化instance时只有一个进程,这个方式在加载Singleton类的时候,instance可以没有被初始化,因为LazyHolder类并没有被使用,只有当调用getInstance方法时才会显示装载LazyHolder类,从而实例化instance。
public class Singleton {
private Singleton(){};
//创建静态内部类
public static class LazyHolder {
private static final Singleton INSTANCE = new Singleton();
}
//使用static final保证single唯一
private static final Singleton single = new Singleton();
//提供静态方法供外部调用
public static final getInstance(){
return LazyHolder.INSTANCE;
}
}
单例模式 饿汉式
public class Singleton {
//创建私有的构造方法
private Singleton(){};
//使用static final保证single唯一
private static final Singleton single = new Singleton();
//提供静态方法供外部调用
public static getInstance(){
return this.single;
}
}
饿汉式在类初始化的时候就已经创建了唯一的静态对象供其他类调用,所以是线程安全的。但是因为需要在类初始化的时候就创建静态对象,占用内存空间,在实例需要大量资源的时候不推荐使用。
单例模式 枚举式
//enum是java1.5之后添加的
public enum RegisterSingleton {
INSTANCE;
public RegisterSingleton getInstance() {
return INSTANCE;
}
}
最牛逼高端大气上档次的单例模式,也是effective java推荐使用的方式,但是只支持java1.5及以上版本使用
通过静态内部类实现单例模式
public class InnerSingleton {
public static InnerSingleton getInstance(){
return SingLetonHolder.INNER_SINGLETON;
}
private static class SingLetonHolder{
private static final InnerSingleton INNER_SINGLETON = new InnerSingleton();
}
}