Java中单例模式定义:“一个类有且仅有一个实例,并且自行实例化向整个系统提供。”
特点:
- 单例类只能有一个实例。
- 单例类必须自己创建自己的唯一实例。
- 单例类必须给所有其他对象提供这一实例。
//这种方法是线程不安全的,如果并发则会创建多个对象 class SinglePattern{ private static SinglePattern instance ; //1.构造方法私有化 private SinglePattern() { } //2.提供一个全局访问点 public static SinglePattern getInstance() { if(instance == null) { instance = new SinglePattern(); } return instance; } }
多线程有一个锁机制。使用synchronized修饰。我们可以锁住获取对象的方法。代码如下:
/** * 加锁后的,单例模式类 * @author wanghao * */ class SinglePattern{ private static SinglePattern instance ; //1.构造方法私有化 private SinglePattern() { } //2.提供一个全局访问点 加锁后 public static synchronized SinglePattern getInstance() { if(instance == null) { instance = new SinglePattern(); } return instance; } }
众所周知线程安全就等于效率会相对低点。所有经过改造优化,出现另一种双重判断方式。代码如下:
/** * 加锁后的,单例模式类 +优化后 * @author wanghao * */ class SinglePattern{ private static SinglePattern instance ; //1.构造方法私有化 private SinglePattern() { } //2.提供一个全局访问点 加锁后 public static SinglePattern getInstance() { if(instance == null) { synchronized(SinglePattern.class) { if(instance == null) { instance = new SinglePattern(); } } } return instance; } }
单例模式重点就一个对象,这样理论上会是创建次数少获取的次数多。所以,我们只需加锁创建对象的方式,而判断是否为null,可以不加锁。可以提高效率。
如果按前面一种方式,如果高并发10个线程同时访问,则需要耗费10*(等待时间+判断时间),
而如果用第二张方式,如果通用10个线程访问,则只需10*(判断时间),如果没有对象则再加上一次判断时间和创建对象的时间。