【多线程案例】单例模式(懒汉模式和饿汉模式)

这篇具有很好参考价值的文章主要介绍了【多线程案例】单例模式(懒汉模式和饿汉模式)。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1. 什么是单例模式?

提起单例模式,就必须介绍设计模式,而设计模式就是在软件设计中,针对特殊问题提出的解决方案。它是多年来针对一些常见的问题的解决方法,具有良好的可复用性、可扩展性和可维护性。
标准的设计模式有23种,单例模式就是最常见的一种,其目的是确认一个类只有一个实例对象,并且可以提供一个全局访问点来访问该实例。
单例就是指一个类的实例只有一个,即该类的所有对象都指向用同一个实例。
而多数单例模式并没有结合多线程,在多线程环境下运行有时会出现线程安全问题,所以下面不仅介绍如何实现单例模式,还有单例模式结合多线程使用时的相关知识。

2. 立即加载/“饿汉模式”

立即加载一般还被称作饿汉模式,根据立即,饿汉可以看出十分的急,所以在饿汉模式中,这样单例中的唯一实例对象就被创建。

创建MyObject.java代码如下:

//单例模式、饿汉模式
public class MyObject {
    //进行封装,防止创建新的对象
    private static MyObject object = new MyObject();
    private MyObject(){};
    //通过这个方法获得对象
    public static MyObject getObject(){
        return object;
    }
}

创建线程类MyThread.java:

public class MyThread extends Thread{
    @Override
    public void run() {
        System.out.println(MyObject.getObject().hashCode());
    }
}

创建运行类Run.java:

public class Run {
    //测试单例模式对象是同一个
    public static void main(String[] args) {
        MyThread t1 = new MyThread();
        MyThread t2 = new MyThread();
        MyThread t3 = new MyThread();
        t1.start();
        t2.start();
        t3.start();
    }
}

运行结果:
【多线程案例】单例模式(懒汉模式和饿汉模式),Java多线程编程,单例模式,javascript,开发语言,java
运行结果相同,说明对象是同一个,成功实现了立即加载型单例设计模式。

3. 延时加载/“懒汉模式”

延时,懒汉可以看出代码并不着急,所以懒汉模式型单例模式中的对象并不像饿汉模式中没有调用前就创建完成,而是在第一调用方法实例时才被创建。
对比饿汉模式:
优点:会减少内存资源浪费。
缺点:多线程环境并发运行,可能会出现线程安全。

3.1 第一版

创建类MyObjectLazy.java,代码如下:

public class MyObjectLazy {
    //单例模式、懒汉模式
    private static MyObjectLazy myObjectLazy = null;
    private static Object lock = new Object();
    private MyObjectLazy(){};
    public static MyObjectLazy getMyObjectLazy(){
        if(myObjectLazy != null){
            return myObjectLazy;
        }else{
            myObjectLazy = new MyObjectLazy();
        }
        return myObjectLazy;
    }
 }

创建线程类MyThreadLazy.java:

public class MyThreadLazy extends Thread{
    @Override
    public void run() {
        System.out.println(MyObjectLazy.getMyObjectLazy().hashCode());
    }
}

创建运行类RunLazy.java:

public class RunLazy {
    //测试对象是不是同一个,是的话就是安全的单例模式
    public static void main(String[] args) {
        MyThreadLazy t1 = new MyThreadLazy();
        MyThreadLazy t2 = new MyThreadLazy();
        MyThreadLazy t3 = new MyThreadLazy();
        t1.start();
        t2.start();
        t3.start();
    }
}

运行结果:
【多线程案例】单例模式(懒汉模式和饿汉模式),Java多线程编程,单例模式,javascript,开发语言,java
结果不同,所以并不是单例模式,其中有问题,造成线程不安全。

3.2 第二版

第一版生成不同对象,所以造成非线程安全,我们可以做出一点修改,对代码加上锁。
修改后的MyObjectLazy.java:

    public static MyObjectLazy getMyObjectLazy(){
        synchronized (lock){
            if(myObjectLazy == null){
                myObjectLazy = new MyObjectLazy();
            }
        }
        return myObjectLazy;
    }

运行结果:
【多线程案例】单例模式(懒汉模式和饿汉模式),Java多线程编程,单例模式,javascript,开发语言,java
说明这个单例模式是正确实现了。

3.3 第三版

但是第二版又暴露一个问题,上面加锁后相当于整个方法都加锁,上面一个线程没有释放锁,下一个线程将无法运行,造成效率低下。
所以我们继续修改,修改后的MyObjectLazy.java:

    public static MyObjectLazy getMyObjectLazy(){
        try{
            if(myObjectLazy == null){
                Thread.sleep(1000);
                synchronized (lock){
                    myObjectLazy = new MyObjectLazy();
                }
            }
        }catch(InterruptedException e){
            e.printStackTrace();
        }
        return myObjectLazy;
    }

运行结果:
【多线程案例】单例模式(懒汉模式和饿汉模式),Java多线程编程,单例模式,javascript,开发语言,java
运行结果又不同了,创建出了三个对象,为什么?这是因为虽然上了锁,但是if已经判断,只是new对象时串行。
虽然效率提高了,但这并不是单例模式。

3.4 第四版

我们可以使用DCL双检查锁机制来实现,进行两次if判断,使线程安全。
修改后MyObjectLazy.java:

    //再一次修改代码,加锁只加一块,并且应用DCL双检查机制来实现多线程环境下的延时加载单例模式,保证线程安全
    public static MyObjectLazy getMyObjectLazy(){
        try{
            if(myObjectLazy == null){
                Thread.sleep(1000);
                synchronized (lock){
                    if(myObjectLazy == null) {
                        myObjectLazy = new MyObjectLazy();
                    }
                }
            }
        }catch(InterruptedException e){
            e.printStackTrace();
        }
        return myObjectLazy;
    }

运行结果:
【多线程案例】单例模式(懒汉模式和饿汉模式),Java多线程编程,单例模式,javascript,开发语言,java
使用双检查锁功能,成功解决了懒汉模式遇到多线程的问题。DCL经常出现在此场景下,我们要学会应用。文章来源地址https://www.toymoban.com/news/detail-690405.html

到了这里,关于【多线程案例】单例模式(懒汉模式和饿汉模式)的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 设计模式第一课-单例模式(懒汉模式和饿汉模式)

    个人理解:单例模式实际就是通过类加载的方式获取到一个对象,并且保证这个对象在使用中只有一个,不允许再次被创建 1、懒汉模式的基础写法 代码解释: (1)、编写LazySingleton类的时候,需要将成员属性设定为static,这样才会是类属性 (2)、重写构造方法,将其设置

    2024年02月05日
    浏览(44)
  • c++单例模式包括懒汉模式和饿汉模式(优劣势分析和改进方法)

    在整个软件的运行过程中,让整个类有且只有一个实例化对象存在于整个进程中。 是最简单的一个设计模式,然后再项目开发中也是使用最广的。 1.节省资源:再整个软件的运行过程中,只有一个实例化对象,不用重新分配新的堆空间。 2.数据的传递:由于单例只会创建一个

    2024年02月21日
    浏览(39)
  • 【Java|多线程与高并发】设计模式-单例模式(饿汉式,懒汉式和静态内部类)

    设计模式是一种在软件开发中常用的解决复杂问题的方法论。它提供了一套经过验证的解决方案,用于解决特定类型问题的设计和实现。设计模式可以帮助开发人员提高代码的可重用性、可维护性和可扩展性。 设计模式有很多,本文主要介绍单例模式. 单例模式是一种创建型设

    2024年02月11日
    浏览(55)
  • 关于Java中单例模式(饿汉模式和懒汉模式)的简析

    目录 一.什么是单例模式 二.饿汉模式和懒汉模式 饿汉模式 代码 懒汉模式 代码 关于多线程安全的问题 如何解决懒汉模式多线程安全问题 双if判断 简单来说,就是我们在程序中通过代码进行限制,在该程序中 只能创建一个对象 因为只能创建一个对象,所以对于我们而言就有两种

    2024年02月10日
    浏览(81)
  • Java中单例(单态、原子)设计模式(饿汉式/懒汉式)

    先看文章目录,大致了解知识点结构,直接点击文章目录可以跳转到文章指定位置。 设计模式就是设计出来的固定问题的解决方法,描述了在软件设计过程中的一些不断重复发生的问题和解决方案。遇到类似问题的时候可以直接使用现成的模式方案。 ①单例模式中一个类只

    2024年02月04日
    浏览(43)
  • Java单例模式的五种实现方式 懒汉式 饿汉式 双重校验锁 静态变量 静态内部类 枚举实现单例模式等

    Java单例模式是一种设计模式,用于确保一个类只有一个实例,并提供全局访问点以获取该实例。它通常用于需要共享资源或控制某些共享状态的情况下。 懒汉式:在类加载的时候就创建对象,要再调用方法时才创建对象,减少内存开销。 饿汉式:再类加载的时候就实例化对

    2024年04月27日
    浏览(36)
  • 【单例模式】饿汉模式和懒汉模式的单例模式

    设计模式是一种 在软件设计中经过验证的解决问题的方案或者模版 。它们是从实践中总结出来的,可以帮助解决常见的设计问题,提高代码的重用性、维护性和扩展性。 设计模式可以分为三大类: 创建型模式(Creational Patterns) :创建型模式关注对象的实例化过程,包括如

    2024年02月16日
    浏览(68)
  • 设计模式之单例模式(懒汉, 饿汉)

    单例模式是一种常用的软件设计模式, 该模式的主要目的是确保某一个类在内存中只能有一个实例对象, 通过单例模式的方法创建的类在当前进程中只有一个实例对象. 常见的单例模式有两种: 饿汉式, 这里的 “饿” 意义表述不够清晰, 用 “急” 来表述意义更加容易联想一些

    2024年02月22日
    浏览(52)
  • 单例模式(饿汉式单例 VS 懒汉式单例)

    所谓的单例模式就是保证某个类在程序中只有一个对象 1.构造方法私有化(保证对象的产生个数)         创建类的对象,要通过构造方法产生对象        构造方法若是public权限,对于类的外部,可以随意创建对象,无法控制对象个数       构造方法私有化,这样类的外

    2024年02月09日
    浏览(42)
  • JavaEE:单例模式(饿汉模式和懒汉模式)精讲

    前言 什么是单例模式? 其实用通俗的话就是程序猿约定俗成的一些东西,就比如如果你继承了一个抽象类,你就要重写里面的抽象方法,如果你实现了一个接口,你就要重写里面的方法。如果不进行重写,那么编译器就会报错。这其实就是一个规范。 而单例模式能保证某个

    2024年02月04日
    浏览(49)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包