单例模式是oop(面向对象编程)语言的一种概念,顾名思义,就是一个类只能有一个实例对象。
单例模式分为两种:1,懒汉式单例 2,饿汉式单例
懒汉式单例
特点:当需要使用对象的时候才进行实例化。
传统实现代码:
class Singleton{
//设置私有构造方法
private Singleton(){}
//声明一个Singleton对象为obj
private static Singleton obj;
//加锁保证obj只能实例化一次,时间换空间
public static synchronized Singleton getInstance(){
if(obj == null){
obj=new Singleton();
}
return obj;
}
}
传统实现方式中,每次获取实例都要被synchronized关键字串行化,即使已经生成了对象实例。
所以会导致大量不必要的开销
而我们加锁的目的是为了防止生成多个实例,因此其实只需要对生成实例的代码加锁.
可以用双重检查法
class Singleton{
//设置私有构造方法
private Singleton(){}
// 最后解释volatile关键字
private volatile static Singleton obj;
//获取实例对象的方法
public static Singleton getInstance(){
//如果已有实例则直接返回,不走锁
if(obj==null){
//仅在没生成实例时加锁控制,使并发访问串行化
synchronized(Singleton.class){
//多个线程会按序执行到此处,需要再次检查是否已经实例化
if(obj==null){
obj = new Singleton();
}
}
}
return obj;
}
}
饿汉式单例
饿汉式单例的特点是:类加载时便实例化对象。
能够在第一时间实例化对象,供其他方法使用,是拿空间换时间的方案。
传统实现代码:
Class Singleton{
//私有构造方法
private Singleton(){ };
//类加载时就实例化对象 加static
private static Singleton obj=new Singleton();
public static Singleton getInstance(){
return obj;
}
}
优化实现:
上述传统方式中,由于类加载时就实例化对象,因此当我们调用这个类的其它静态方法时,也会触发类加载,从而实例化单例独享,会导致空间的暂时浪费。
优化代码实现:
class Singleton{
// 私有构造函数
private Singleton() {}
// 静态内部类
private static class SingletonHolder {
private static Singleton instance = new Singleton();
}
public static Singleton getInstance(){
return SingletonHolder.instance;
}
}
上述两种实现方式中,最推荐这种优化后的饿汉式实现,利用static保证线程安全,利用静态内部类节约了空间,实现lazy-loading(懒加载),而且代码非常简短,可谓一箭三雕。