当前位置: 首页 > article >正文

Java EE--多线程(二)

目录

四、多线程案例之--单例模式

3.1 单例模式

3.2 怎么去设计一个单例?

 饿汉模式

 懒汉模式

3.3 两种模式的总结

四、多线程案例之--单例模式

4.1 单例模式

是校招中最常考的设计模式之一.

啥是设计模式?

设计模式好比象棋中的 " 棋谱 ". 红方当头炮 , 黑方马来跳 . 针对红方的一些走法 , 黑方应招的时候有一些固定的套路. 按照套路来走局势就不会吃亏 .
软件开发中也有很多常见的 " 问题场景 ". 针对这些问题场景 , 大佬们总结出了一些固定的套路 . 按照这个套路来实现代码, 也不会吃亏 .

 单例模式能保证某个类在程序中只存在唯一一份实例, 而不会创建出多个实例.

这一点在很多场景上都需要. 比如 JDBC 中的 DataSource 实例就只需要一个.

(定义了数据库的用户名,密码,连接串,通过DataSource的实例对象获取数据库的连接)

单例模式具体的实现方式 , 分成 " 饿汉 " " 懒汉 " 两种 .

4.2 怎么去设计一个单例?

1.口头约定

对外提供一个方法,要求大家使用这个对象的时候,通过这个方法来获取

(不靠谱,不采用)

2.使用编程语言本身的特性来处理

首先要分析清楚,在Java中哪些对象是全局唯一的 

.class对象 比如String.class  类对象

 

 

 饿汉模式

既然是单例那么通过new的方式去获取对象是有歧义的 那么就不能让外部去new这个对象

Singleton singleton = new Singleton();
//构造方法私有化
private Singleton(){}
public static Singleton getInstance(){
 return instance;
}//用static修饰方法

private static Singleton instance = new Singleton();
//类似于这种类一加载就完成初始化的方式 称为饿汉模式
//书写简单不易出错

懒汉模式

避免程序启动的时候浪费过多的系统资源,当程序使用这个对象时再对它进行初始化

//定义一个类成员变量
private static SingletonLazy instance = null;
public static SingletonLazy getInstance(){
//在获取成员变量的时候判断是否已经初始创建
//如果没有则创建出来
if(instance == nul){
     instance = new SingletonLazy();
  }
return instance;
}

多线程环境下获取单例对象:

  // 创建多个线程,并获取单例对象
        for (int i = 0; i < 10; i++) {
            Thread thread = new Thread(() -> {
                // 获取单例对象,并打印
                SingletonLazy instance = SingletonLazy.getInstance();
                System.out.println(instance);
            });
            // 启动线程
            thread.start();
        }
    }
}

                                                                                

 通过检查发现获取到了不同的对象,出现了线程不安全

分析造成线程不安全的原因:

 为了解决这个问题,可以把初始化代码加锁:

public synchronized static SingletonLazy getInstance(){

 可以看到依然出现了线程安全问题,那么就需要扩大锁的力度

 

输出正常、

但是还剩一个非常严重的问题!

 

 举个栗子:

 为了避免过度竞争消耗,加入一层判断

 public static SingletonDCL getInstance() {
        // 为了让后面的线程不再获取锁,避免了锁竞争造成的资源浪费
        if (instance == null) {
            synchronized (SingletonDCL.class) {
                // 完成初始化操作,只执行一次
                if (instance == null) {
                    instance = new SingletonDCL();
                }
            }
        }
        //双重检查锁

通过加synchnized关键字解决了原子性,内存可见性问题,那有序性如何保证?

那么就需要给共享变量加volatile关键字

public class SingletonDCL {
    // 定义一个类成员变量
    private volatile static SingletonDCL instance;

    // 构造方法私有化
    private SingletonDCL() {
    }

    public static SingletonDCL getInstance() {
        // 为了让后面的线程不再获取锁,避免了锁竞争造成的资源浪费
        if (instance == null) {
            synchronized (SingletonDCL.class) {
                // 完成初始化操作,只执行一次
                if (instance == null) {
                    instance = new SingletonDCL();
                }
            }
        }
        // 返回实例对象
        return instance;
    }
}

 4.3 两种模式的总结

 


http://www.kler.cn/a/18344.html

相关文章:

  • Java Stream 流常用操作大全
  • 稀疏视角CBCT重建的几何感知衰减学习|文献速递-基于深度学习的病灶分割与数据超分辨率
  • 51c视觉~合集6
  • LLMs之PDF:zeroX(一款PDF到Markdown 的视觉模型转换工具)的简介、安装和使用方法、案例应用之详细攻略
  • uniapp分享功能
  • 009_SSH_Mysql图书管理系统(学生注册 借书 还书 绵阳)——lwplus87(免费送)
  • Linux命令·netstat
  • electron +VUE 获取本地MAC地址
  • 又一起数据泄露事件五个月内的第二次
  • OpenPCDet系列 | 7.PointPillars模型测试KITTI数据集流程解析
  • 文件压缩与解压性能对比 lzop, gzip
  • CentOS 7 常用的命令,你知道多少?
  • 5.9-5.10学习总结
  • PDN Handover流程介绍
  • Java RSA密钥转换,从RSAPrivateKey得到RSAPublicKey
  • HTML5字体集合的实践经验
  • ( 位运算 ) 268. 丢失的数字 ——【Leetcode每日一题】
  • 当生命里有程序来串门——一个北邮信通大一学生的漫谈
  • Linux权限 - 概念与管理 | 文件权限的修改与转让 【详解】
  • 给你安利一款不需要魔法就能免费使用的idea插件Bito-ChatGPT
  • IO-Netty
  • Linux_红帽8学习笔记分享_10(SELinux管理与防火墙)
  • SpringBoot——入门程序的简单介绍
  • wiringPi常用函数
  • 使用 ChatGPT 辅助学习——为自己找一个老师
  • docker部署SpringBoot项目