单例模式
一个类只有一个实例,并提供一个全局访问此实例的点,哪怕多线程同时访问。
单例模式主要解决了一个全局使用的类被频繁的创建和消费
的问题。
单例模式的案例场景
- 数据库的连接池不会反复创建
- spring中一个单例模式bean的生成和使用
- 在我们平常的代码中需要设置全局的一些属性保存
七种单例模式的实现
1.懒汉模式(线程不安全,懒加载)
public static class Singleton_01 {
private static Singleton_01 instance;
private Singleton_01() {}
public static Singleton_01 getInstance() {
if (null != instance) {
return instance;
}
instance = new Singleton_01();
return instance;
}
}
非常标准且简单地单例模式。
满足了懒加载,但是线程不安全。
2.懒汉模式(线程安全,懒加载)
public static class Singleton_02 {
private static Singleton_02 instance;
private Singleton_02() {}
public static synchronized Singleton_02 getInstance() {
if (null != instance) {
return instance;
}
instance = new Singleton_02();
return instance;
}
}
线程安全,但是效率低,不建议使用。
3.饿汉模式(线程安全)
public class Singleton_03 {
private static Singleton_03 instance = new Singleton_03();
private Singleton_03() { }
public static Singleton_03 getInstance() {
return instance;
}
}
饿汉模式,在程序启动的时候直接运行加载。
4.使用内部静态类(线程安全、懒加载)
public class Singleton_04 {
private static class SingletonHolder {
private static Singleton_04 instance = new Singleton_04();
}
private Singleton_04() { }
public static Singleton_04 getInstance() {
return SingletonHolder.instance;
}
}
通过内部静态类实现了懒加载和线程安全,推荐使用。
5.锁+双重校验(线程安全,懒加载)
private class Singleton_05 {
private static volatile Singleton_05 instance;
private Singleton_05() { }
public static Singleton_05 getInstance() {
if (null != instance) {
return instance;
}
synchronized (Singleton_05.class) {
if (null == instance) {
instance = new Singleton_05();
}
}
return instance;
}
}
相较于线程安全的懒汉模式,这种方法效率更高。
6.CAS【AtomicReference】(懒加载,线程安全)
public class Singleton_06 {
private static final AtomicReference<Singleton_06> INSTANCE = new AtomicReference<Singleton_06>();
private Singleton_06() { }
public static final Singleton_06 getInstance() {
for(;;) {
Singleton_06 instance = INSTANCE.get();
if (null != instance) {
return instance;
}
INSTANCE.compareAndSet(null, new Singleton_06());
return INSTANCE.get();
}
}
}
AtomicReference<V>
可以封装引用一个V实例,支持并发访问。
使用CAS的好处就是不需要使用传统的加锁方式保证线程安全,而是依赖于CAS的忙等算法,依赖于底层硬件的实现,来保证线程安全。相对于其他锁的实现,没有线程的切换和阻塞,也就没有了额外的开销,并且可以迟迟较大的并发性。
但CAS的一个缺点就是忙等,如果一直没有获取到将会处于死循环中。
7.枚举单例(线程安全)
public enum Singleton_07 {
INSTANCE;
private Map<String, String> cache = new ConcurrentHashMap<>();
public Map<String, String> getCache() {
return cache;
}
public void addToCache(String key, String value) {
cache.put(key, value);
}
}
《Effective Java》作者推荐使用枚举的方式解决单例模式,这种方法解决了线程安全、自由串行化和单一实例的问题。
调用时也很方便:Singleton_07.INSTANCE.getCache();
枚举单例十分简洁,并且它无常地提供了串行化机制,绝对防止对此实例化(毕竟是枚举)。
但是它在继承的场景下是不可使用的,并且不是懒加载(毕竟是枚举)。
1.本站内容仅供参考,不作为任何法律依据。用户在使用本站内容时,应自行判断其真实性、准确性和完整性,并承担相应风险。
2.本站部分内容来源于互联网,仅用于交流学习研究知识,若侵犯了您的合法权益,请及时邮件或站内私信与本站联系,我们将尽快予以处理。
3.本文采用知识共享 署名4.0国际许可协议 [BY-NC-SA] 进行授权
4.根据《计算机软件保护条例》第十七条规定“为了学习和研究软件内含的设计思想和原理,通过安装、显示、传输或者存储软件等方式使用软件的,可以不经软件著作权人许可,不向其支付报酬。”您需知晓本站所有内容资源均来源于网络,仅供用户交流学习与研究使用,版权归属原版权方所有,版权争议与本站无关,用户本人下载后不能用作商业或非法用途,需在24个小时之内从您的电脑中彻底删除上述内容,否则后果均由用户承担责任;如果您访问和下载此文件,表示您同意只将此文件用于参考、学习而非其他用途,否则一切后果请您自行承担,如果您喜欢该程序,请支持正版软件,购买注册,得到更好的正版服务。
5.本站是非经营性个人站点,所有软件信息均来自网络,所有资源仅供学习参考研究目的,并不贩卖软件,不存在任何商业目的及用途
暂无评论内容