• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

Java EE 初阶---多线程二

武飞扬头像
点子李
帮助1

目录

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

4.1 单例模式

4.2 怎么去设计一个单例?

 饿汉模式

 懒汉模式

 4.3 两种模式的总结


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

4.1 单例模式

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

啥是设计模式?

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

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

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

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

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

4.2 怎么去设计一个单例?

1.口头约定

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

(不靠谱,不采用)

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

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

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

 学新通

 学新通

 饿汉模式

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

Singleton singleton = new Singleton();
  1.  
    //构造方法私有化
  2.  
    private Singleton(){}
  1.  
    public static Singleton getInstance(){
  2.  
    return instance;
  3.  
    }//用static修饰方法
  4.  
     
  5.  
    private static Singleton instance = new Singleton();
  6.  
    //类似于这种类一加载就完成初始化的方式 称为饿汉模式
  7.  
    //书写简单不易出错

懒汉模式

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

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

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

  1.  
    // 创建多个线程,并获取单例对象
  2.  
    for (int i = 0; i < 10; i ) {
  3.  
    Thread thread = new Thread(() -> {
  4.  
    // 获取单例对象,并打印
  5.  
    SingletonLazy instance = SingletonLazy.getInstance();
  6.  
    System.out.println(instance);
  7.  
    });
  8.  
    // 启动线程
  9.  
    thread.start();
  10.  
    }
  11.  
    }
  12.  
    }

             学新通                                                                   

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

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

学新通

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

public synchronized static SingletonLazy getInstance(){

学新通

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

学新通

 学新通

输出正常、

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

学新通

 学新通

 举个栗子:

学新通

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

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

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

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

  1.  
    public class SingletonDCL {
  2.  
    // 定义一个类成员变量
  3.  
    private volatile static SingletonDCL instance;
  4.  
     
  5.  
    // 构造方法私有化
  6.  
    private SingletonDCL() {
  7.  
    }
  8.  
     
  9.  
    public static SingletonDCL getInstance() {
  10.  
    // 为了让后面的线程不再获取锁,避免了锁竞争造成的资源浪费
  11.  
    if (instance == null) {
  12.  
    synchronized (SingletonDCL.class) {
  13.  
    // 完成初始化操作,只执行一次
  14.  
    if (instance == null) {
  15.  
    instance = new SingletonDCL();
  16.  
    }
  17.  
    }
  18.  
    }
  19.  
    // 返回实例对象
  20.  
    return instance;
  21.  
    }
  22.  
    }
学新通

学新通学新通

 4.3 两种模式的总结

 学新通

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /boutique/detail/tanhigfich
系列文章
更多 icon
同类精品
更多 icon
继续加载