单例模式有很多种实现方式,目的是为了控制类的实例个数,确保一个类只有一个实例
在23种设计模式中,单例模式可以说是最简单的一种了,实现它的要素有如下几点:
- 私有的构造方法(不让外部实例化)
- 私有的静态实例(给公有静态方法调用)
- 公有的静态访问方法
常见的单例模式有以下几种:
- 饿汉式
一开始就创建一个类的实例(不管有没有被用到),不存在线程安全问题,第一次比较慢
public class Singleton{
//私有的构造方法
private Single(){}
//私有的静态实例
private static Singleton instance = new Singleton();
//共有的静态访问方法
public static Singleton getInstance(){
return instance;
}
}
- 懒汉式
程序需要的时候再去加载(体现延迟加载思想,所以叫懒汉式)
public class Singleton{
//私有构造方法
private Singleton(){}
//私有静态实例
private static Singleton instance;
//公有的静态访问方法
public static Singleton getInstance(){
if(instance == null){
//需要的时候才实例化
instance = new Singleton();
}
return instance;
}
}
这种方法有线程安全问题,在多线程情况下,容易实例化多个实例
为了解决线程安全问题,我们可以使用synchronized关键字,保证一个线程访问时,其他线程的访问被堵塞
public class Singleton{
//私有构造方法
private Singleton(){}
//私有静态实例
private static Singleton instance;
//公有的静态访问方法
//使用synchronized保证线程安全
public static synchronized Singleton getInstance(){
if(instance == null){
//需要的时候才实例化
instance = new Singleton();
}
return instance;
}
}
这种方法也有弊端,容易造成阻塞时间过长的问题
为了改善这个问题,可以把synchronized放在if条件语句内
public class Singleton{
//私有构造方法
private Singleton(){}
//私有静态实例
private static Singleton instance;
//公有的静态访问方法
public static Singleton getInstance(){
if(instance == null){
synchronized(Singleton.class){
//双重校验
if (instance == null) {
instance = new Singleton();
}
}
}
return instance;
}
}
或者加/解锁
if(instance == null){
//加锁
lock.lock();
if(instance ==null){
instance = new Singleton();
}
//解锁
lock.unlock();
}
终极方式(推荐使用)
public class Singleton{
//私有构造方法
private Singleton(){}
//在私有的静态内部类中进行私有的静态实例化
private static class Psc{
private static final Singleton INSTANCE = new Singleton();
}
//公有的静态访问方法
public static synchronized Singleton getInstance(){
return Psc.INSTANCE;
}
}
这种方式利用类的加载机制,静态块代码只加载一次,同时也避免了多线程的问题。