singleton单例模式小结
2024-08-26 22:06:50
1.饿汉模式
public class SingletonEntity2 { // 在类加载的时候创建对象:饿汉模式
public static SingletonEntity2 obj = new SingletonEntity2(); // 构造方法私有化
private SingletonEntity2(){} public static SingletonEntity2 getInstance(){
return obj;
} }
2.懒汉模式
public class SingletonEntity { // 静态变量存放在方法区中,类加载的时候赋值,而且只会赋值一次,懒汉模式
public static SingletonEntity obj = null; // 构造方法私有化
private SingletonEntity() {} // 对外提供获取实例的公开的静态的方法
public static SingletonEntity getInstance() {
if (obj == null) {
obj = new SingletonEntity();
System.out.println("新创建实例");
}
System.out.println("直接返回实例");
return obj;
} }
3.测试类
public static void main(String[] args) { SingletonEntity obj1 = SingletonEntity.getInstance();
SingletonEntity obj2 = SingletonEntity.getInstance();
System.out.println(obj1 == obj2); // true }
==========================================================================================================================================
懒汉模式不安全性测试:
1.起现成类:
public class RunnableThreadTest implements Runnable { @Override
public void run() { SingletonEntity obj = SingletonEntity.getInstance();
System.out.println(Thread.currentThread().getName()+" "+obj); } }
2.测试类:
public class SingletonTest { public static void main(String[] args) { Thread thread1 = new Thread(new RunnableThreadTest());
Thread thread2 = new Thread(new RunnableThreadTest());
thread1.start();
thread2.start(); } }
3.运行结果:
Thread-0 com.beijing.singleton.SingletonEntity@406866f9
Thread-1 com.beijing.singleton.SingletonEntity@25eb939e
==========================================================================================================================================
改善结果:推荐使用双检查锁机制
public class SingletonEntity { // 静态变量存放在方法区中,类加载的时候赋值,而且只会赋值一次,懒汉模式
public static volatile SingletonEntity obj = null; // 构造方法私有化
private SingletonEntity() {
} // 对外提供获取实例的公开的静态的方法
public static SingletonEntity getInstance() {
try {
// 双检查所机制
if (obj == null) {
synchronized (SingletonEntity.class) {
if (obj == null) {
Thread.sleep(1000);
obj = new SingletonEntity();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
return obj;
} }
为什么要用volatile修饰instance?
原因:在于instance = new SingletonEntity()的时候,在内存中实际上是分3步执行的:
1)分配对象的内存空间:memory = allocate();
2)初始化对象:ctorInstance(memory);
3)指向分配的地址:instance =memory
多线程在执行的时候,2 3可能发生重排序。即有可能线程A执行到第3步的时候,读取到instance不为null,就返回。实际上此时还未执行第二部即未初始化。
加上volatile就可以避免2 3步重排序来保证线程安全。
最新文章
- Python 字符串操作及string模块使用
- Bravebeart
- 无废话SharePoint入门教程二[SharePoint发展、工具及术语]
- 通过pip安装模块
- 堆栈指针 ---delete 使用
- 通过PowerShell获取Windows系统密码Hash
- MFC架构
- input[type=text]点击之后无边框, 一进页面就显示光标
- Jquery实现购物车物品数量的加减特效
- 解决CSS各种IE各种兼容问题(Google解决方案)
- (转)ASP.NET Identity登录原理 - Claims-based认证和OWIN
- XML注入介绍--XXE,XEE,xpath等
- 【COM学习】之一、QueryInterface
- Java中Return和Finally运行顺序的实现
- bzoj4318: OSU!&;&;CF235BLet's Play Osu!
- 如何在Eclipse中安装PDT插件来开发PHP
- Javascript 方法apply和call的差别
- django drf json格式化日期时间带T的问题 基于python的解决方法
- [PKUSC2018]星际穿越(倍增)
- Flask依赖和启动流程回顾