java实现线程安全的单例模式

葡萄籽pp      2022-05-08     181

关键词:

一、平时使用的软件中,例如 回收站、线程池、文件系统等,都只有一个实例,这些都是单例模式的典型应用。

  单例模式:确保某个类只有一个实例,并提供一个全局访问点来访问这个实例。

  单例模式有三个要点:

    1. 某个类只能有一个实例

    2. 必须自行创建这个实例

    3. 必须自行向整个系统提供这个实例。

  以上三个要点提示着我们的代码编写需要注意,构造函数必须私有,否则在其他类中便可以调用构造函数创建实例,难以保证实例的唯一性。

二、单例模式分为饿汉模式和懒汉模式

//饿汉模式:(线程安全)
public class Singleton1 {
//    静态私有成员变量
    private static Singleton1 instance = new Singleton1();
//    私有构造函数
    private Singleton1() {
    }
//    静态公有工厂方法,返回唯一实例
    public static Singleton1 getInstance() {
        return instance;
    }
}

 

// 懒汉模式:(线程不安全,需要通过双重检查锁定机制控制)
public class Singleton2 {
//    静态私有成员变量
    private static Singleton2 instance = null;
//    私有构造函数
    private Singleton2() {
    }
//    静态公有工厂方法,判断成员变量是否为空,不为空则实例化
    public static Singleton2 getInstance() {
        if(instance == null)
            instance = new Singleton2();
        return instance;
    }
}

  优缺点:

   饿汉模式不需要考虑线程安全问题,调用速度和访问速度优于懒汉模式,但是由于它不管是否被调用都会提前创建类的实例,所以资源利用效率比较低,系统加载时间比较长。

懒汉模式实现了延迟加载,但是需要克服多个线程同时访问的问题,需要通过双重检查锁定机制进行控制,导致系统性能受到一定影响。

三、下面两个方法实现懒汉模式的线程安全。

  为什么会线程不安全?

   假设有两个线程 A B,其中 A 执行到检查方法,即 if(instance == null) 前,实例都没有被创建,那么 A 会得到 ture 的结果,但是此时调度算法选择 B 线程运行,那么当 B 执行 到 if(instance == null) 时得到的也是 true,那这就很尴尬了,两个线程都会执行 instance = new Singleton2(); 从而创建了两个实例。

  1.双重检查锁定机制。

为了避免以上这种尴尬的情况,需要将这两行代码加上同步锁。但这还不够完美,每次调用函数得到实例都要试图加上一个同步锁,而加锁是一个非常耗时的操作,没有必要的情况下应该尽量避免。基于这种想法,我们可以在加锁前再次判断实例是否为空。这就是双重检查锁定机制。

public class Singleton3 {
//    私有静态成员变量
    private static Singleton3 instance = null;
//    私有构造函数
    private Singleton3() {
    }
//    共有静态工厂方法
    public static Singleton3 getInstance() {
//        判断 instance 是否为空,为空->加锁,创建实例(为了进程安全,再次判断),不为空->返回实例
        if(instance == null) {
            synchronized (Singleton3.class) {
                if(instance == null)
                    instance = new Singleton3();
            }
        }
        return instance;
    }
}

  2. 使用静态内部类创建实例 。JAVA 语言中最好的实现方法)

public class Singleton4 {
//    私有构造函数
    private Singleton4() {
    }
//    静态内部类
    private static class HolderClass{
        private static final Singleton4 instance = new Singleton4();
    }
//    静态公有工厂方法,返回内部类中创建的实例
    public static Singleton4 getInstance() {
        return HolderClass.instance;
    }
}

  当装载 Singleton4 类时,instance 不一定被初始化,因为它是内部类的成员变量。Singleton4 没有被主动使用,只有调用 getInstance 方法时,才会装载 Singleton4 类,从而实例化 instance

使用静态内部类很好得在实现了延迟加载的同时,保证初始化 instance 时只有一个线程。

 

多线程阻塞队列定时器线程安全的单例模式的原理及实现(代码片段)

文章目录1.线程安全版本的单例模式1.1单例模式介绍1.2实现线程安全版本的懒汉模式2.阻塞队列2.1阻塞队列介绍2.2标准库中的阻塞队列2.3实现阻塞队列2.4生产者消费者模型3.定时器3.1定时器介绍3.2标准库中的定时器3.3实现定时器1.... 查看详情

实现线程安全的单例模式

一、双检查锁机制packagesingleton;importorg.slf4j.Logger;importorg.slf4j.LoggerFactory;/***双检查锁机制--单例模式*Createdbydaizengjieon2017/8/29.*/publicclassMySingleton{privatestaticfinalLoggerlogger=LoggerFactory.getL 查看详情

线程安全的单例模式的几种实现

...种常见的设计模式;JavaSingleton模式就为我们提供了这样实现的可能。使用Singleton的好处还在于可以节省内存,因为它限制了实例的个数,有利于Java垃圾回收(garbagecollection)。 单例模式也是一种比较常见的设计模式,它到... 查看详情

线程安全的单例模式

...没用到它,就非常耗费资源。 2. 经典的单例模式实现:Java代码publicclassSingleton{//用一个静态变量来记录Singleton类的唯一实例privatestaticSingletonuniqueInstance;privateSingleton(){}//注意这个方法也是静 查看详情

多线程实现单例模式(饿汉懒汉)实现线程安全的单例模式(双重效验锁)(代码片段)

...一个对象,不能new多个对象。比如:单例模式的两种经典实现单例模式中有两个典型实现:饿汉模式懒汉模式我们来通过一个生活上的例子来给大家讲讲什么是饿汉模式,什么是懒汉模式。 但是在计算机中,普遍认为懒汉模式... 查看详情

java基础——线程安全的单例模式懒汉式

packagesavesingleton;/*使用同步将单例模式中的懒汉式改写成线程安全的@authorzsben@create2020-01-0322:22*/classBank{privateBank(){}privatestaticBankinstance=null;/*publicstaticsynchronizedBankgetInstance(){if(instance==null){ 查看详情

dcl双检查锁机制实现的线程安全的单例模式

publicclassMyObject{privatevolatilestaticMyObjectmyObject;privateMyObject(){}publicstaticMyObjectgetInstance(){try{if(myObject!=null){}else{Thread.sleep(3000);synchronized(MyObject.class){if(myObject= 查看详情

高并发下线程安全的单例模式

...目开发中最为常见的设计模式之一,而单例模式有很多种实现方式,你是否都了解呢?高并发下如何保证单例模式的线程安全性呢?如何保证序列化后的单例对象在反序列化后任然是单例的呢?这些问题在看了本文之后都会一一... 查看详情

c++的单例模式与线程安全单例模式(懒汉/饿汉)

...单例模式  我们都很清楚一个简单的单例模式该怎样去实现:构造函数声明为private或protect防止被外部函数实例化,内部保存一个privatestatic的类指针保存唯一的实例,实例的动作由一个public的类方法代劳,该方法也返回单例类... 查看详情

怎么实现一个线程安全的单例模式

...的,单例模式是考的最多的。线程安全的单例还有很多种实现方法。可以使用静态内部类、双重校验锁、静态代码块等。1、饿汉式public class Singleton()    private static Singleton instance = new ... 查看详情

线程安全的单实例模式

我们都很清楚一个简单的单例模式该怎样去实现:构造函数声明为private或protect防止被外部函数实例化,内部保存一个privatestatic的类指针保存唯一的实例,实例的动作由一个public的类方法代劳,该方法也返回单例类唯一的实例。... 查看详情

java里的单例实现

枚举实现单例线程安全,调用效率高,不能延时加载,可以天然的防止反射和反序列化调用publicenumSingletonFactory{//枚举元素本身就是单例INSTANCE;//添加自己需要的操作publicSingletonObjectgetInstance(){returnnewSingletonObject();}}静态内部类实... 查看详情

线程安全的单例模式(代码片段)

饿汉模式1publicclassSingle23privatestaticSingleinstance=newSingle();45privateSingle()6System.out.println("Single:"+System.nanoTime());789publicstaticSinglegetInstance()10returninstance;1112  查看详情

iodh实现的单例模式

饿汉式单例类不能实现延迟加载,不管将来用不用始终占据内存;懒汉式单例类线程安全控制烦琐,而且性能受影响。有种更好的单例模式叫做InitializationDemandHolder(IoDH)的技术。 publicclassSingleton{privateSingleton(){System.out.println(Si... 查看详情

线程安全的单例模式(代码片段)

...安全问题。若获取  实例方法加synchronized关键字,则能实现线程同步解决线程安全问题,但是多线程下频繁调用会造成巨大的性能开销。    1、双重检查锁及其错误根源      双重检查锁是常见的延迟初始化技术... 查看详情

线程安全的单例模式(代码片段)

一饿汉模式packagecom.thread;publicclassTest8publicstaticvoidmain(String[]args)MyThreadt1=newMyThread();MyThreadt2=newMyThread();MyThreadt3=newMyThread();t1.start();t2.start();t3.start();classMyObjectp 查看详情

多线程下的单例模式

...目开发中最为常见的设计模式之一,而单例模式有很多种实现方式,你是否都了解呢?高并发下如何保证单例模式的线程安全性呢?如何保证序列化后的单例对象在反序列化后任然是单例的呢?这些问题在看了本文之后都会一一... 查看详情

java的单例模式实现

    只能生成一个实例的类是实现了Singleton(单例)模式的类。以下为C#实现单例模式的方式方式一只使用于单线程环境// 把构造函数设为私有函数以禁止他人创建实例// 定义一个静态的实例,在需要的时候创... 查看详情