单例模式是一种常用的软件设计模式,也是一种比较简单的设计模式,取数据连接就是一个典型的单例。
单例模式的三个特点
1,该类只有一个实例
2,该类自行创建该实例(在该类内部创建自身的实例对象)
3,向整个系统公开这个实例接口
单例的几种实现方式以及对比
@方法1:类被加载时就初始化
(缺点:1..对于资源密集,配置开销较大的单体会造成系统内存开销大)
public class Singleton{
private static Singleton instance = new Singleton();
//私有构造函数不允许其他类调用,只允许本来的静态方法调用
privateSingleton(){};
public static Singleton getInstance(){
return instance;
}
}
@方法2:惰性加载Lazyloading(被使用时才被加载)
(缺点:1.对多线程有可能造成多个实例,看注解1)
public class LazySingleton{
private static Lazysingleton instance;//初始为空暂不实例化
privateLazySingleton (){};//私有构造函数不允许其他类调用,只允许本来的静态方法调用
public static LazySingleton getInstance(){
if(instance==null){
unitaryInstance =new LazySingleton();
}
return unitaryInstance;
}
}
@注解1:为什么对多线程不安全?
现在有2个线程分别调用LazySingleton(第一次调用instance未被实例化),当线程一运行到if(instance==null)后instance= new LazySingleton()前,线程二也刚好运行到if(instance==null),这时线程二也满足instance==null,再运行下去会导致线程一、线程二同时创建一个LazySingleton的不同对象,不满足单例模式的要求。
@方法3:双重锁定
public class Singleton{
private static volatile Singleton unitaryInstance;//初始为空暂不实例化
private Singleton (){};//私有构造函数不允许其他类调用,只允许本来的静态方法调用
public static Singleton getInstance(){
if(unitaryInstance==null){
synchronized(LazySingleton.class){//同步块保证同一时间只有一个线程操作
unitaryInstance = new LazySingleton();
}
}
return unitaryInstance;
}
}
@解释:
不能把public static Singleton getInstance(){方法简单的设置为同步方法
public static synchronized SingletongetInstance(){,因为这样每次线程调用的时候都需要等待其他线程退出,会产生严重的性能问题。而方法3中只是第一次调用了同步块,其他时候由于unitaryInstance!=null了所以不会再调用同步块,性能得到很大的提生。
volatile 关键字 1.5新的关键字,可以保证volatile修饰的变量在线程中的值是主内存中最新的(但是如果其他线程正在修改该变量,而且还没同步到主内存,这时变量的值就不能保证最新的值),变量在多线程内存中的交互可以查看下图:(在线程中修改变量的值是把主内存变量的具体值load到线程本地内存中,建立一个变量副本,如后修改副本的值,改完后在某个时间(线程结束前)同步到主内存)