一、什么是单例?
确保一个类只有一个实例,并提供一个全局访问点
二、应用
线程池、缓存、数据库等,只需要一个实例,如果多个实例 会造成异常情况
三、简单实现
1)懒汉式简单实现
①public class Singleton{
private static Singleton singleton;
private Singleton(){}
public static Singleton getInstance(){
if(singletn==null){//位置一
singleton = new Singleton();
}
return singleton;
}
}
注:简单的实现对于多线程会有问题,第一次创建singleton时,线程1正在执行位置一,同时线程2又需要一个singleton的实例,她也执行到位置一,致使线程1,2都获取到一个singleton的实例,造成出现两个singleton实例
②解决多线程的问题,加入synchronized同步锁,只准一个进入去创建实例,重新写getInstance方法
public static synchronized Singleton getInstance(){
if(singletn==null){//位置一
singleton = new Singleton();
}
return singleton;
}
使用synchronized解决了多线程问题,但是性能降低了,每次进入都要判断一下getInstance这个方法是否已经执行完,但是我们只需要第一次实例化singleton时,判断一下是否执行完这个getInstance方法。
③双重检查加锁,在getInstance减少同步,增加性能:
private volatile static Singleton singleton;//volatile关键字:确保;当singleton被实例化成Singleton时,多个线程正确的处理singleton变量
public static Singleton getInstance(){
if(singleton == null){//检查实例,如果不存在,进入同步区
synchronized(Singleton.class){//只有第一次才彻底执行这段代码
if(singleton == null){//再次判空
singleton = new Singleton();
}
}
}
}
注:以上是懒汉式的单例模式,也就是延迟加载,用到singleton的时候才创建一个实例。
2)饿汉式单例模式:
①简单实现:
private static Singleton singleton = new Singleton();
public static Singleton getInstance(){
return singleton;
}
②内部类饿汉式实现方法:
public static Singleton getInstance(){
return SingletonHolder.instance;
}
private static class SingletonHolder{
private static Singleton instance = new Singleton();
}
注:采用饿汉式方法实现单例模式的方法是在类的内部实例化一个静态变量singleton,这是比较好理解的,那么很自然的能想到声明为一个类的静态变量啦。还有一点要注意的哦,那就是该类的构造方法是私有的。这样类就不提供默认的构造函数了,所以也就不可以实例化了
四、总结
1)单例模式确保一个单独实例
2)提供一个全局访问点(getInstance())
3)一个私有构造(Singleton),一个私有静态变量(singleton),一个公有静态方法(getInstance())
来源:https://www.cnblogs.com/wangjinger/p/Singleton.html