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步重排序来保证线程安全。

最新文章

  1. Python 字符串操作及string模块使用
  2. Bravebeart
  3. 无废话SharePoint入门教程二[SharePoint发展、工具及术语]
  4. 通过pip安装模块
  5. 堆栈指针 ---delete 使用
  6. 通过PowerShell获取Windows系统密码Hash
  7. MFC架构
  8. input[type=text]点击之后无边框, 一进页面就显示光标
  9. Jquery实现购物车物品数量的加减特效
  10. 解决CSS各种IE各种兼容问题(Google解决方案)
  11. (转)ASP.NET Identity登录原理 - Claims-based认证和OWIN
  12. XML注入介绍--XXE,XEE,xpath等
  13. 【COM学习】之一、QueryInterface
  14. Java中Return和Finally运行顺序的实现
  15. bzoj4318: OSU!&&CF235BLet's Play Osu!
  16. 如何在Eclipse中安装PDT插件来开发PHP
  17. Javascript 方法apply和call的差别
  18. django drf json格式化日期时间带T的问题 基于python的解决方法
  19. [PKUSC2018]星际穿越(倍增)
  20. Flask依赖和启动流程回顾

热门文章

  1. 综述论文翻译:A Review on Deep Learning Techniques Applied to Semantic Segmentation
  2. 02 HTML
  3. (二)linux 学习 -- 探究操作系统
  4. 剑指offer28:找出数组中超过一半的数字。
  5. RT-Flash imxrt 系列rt1052 rt1060量产神器宣传
  6. Linux下交换文件说明
  7. PB在已经存在的datawindow中添加数据列的方法
  8. mybatis执行DDL语句
  9. Java LowerBound
  10. sql 语句实现一串数字位数不足在左侧补0的技巧