单例模式实现的多种方式

el/2024/4/20 16:12:18

文章目录

  • 饿汉式构建
  • 懒汉式线程安全构建
  • 静态内置类实现单例模式
  • 线程安全的单例模式: 双重检验锁(DCL)

饿汉式构建

饿汉式,线程不安全
是否 Lazy 初始化:是

是否多线程安全:否

实现难度:易

描述:这种方式是最基本的实现方式,这种实现最大的问题就是不支持多线程。因为没有加锁 synchronized,所以严格意义上它并不算单例模式。
这种方式 lazy loading 很明显,不要求线程安全,在多线程不能正常工作。

/*** @author dustdawn* @date 2019/9/5 15:19*/
public class Singleton {//饿汉构建单例private static Singleton singleton = new Singleton();private Singleton() {}public static Singleton getInstance() {return singleton;}}

懒汉式线程安全构建

懒汉式,线程安全
是否 Lazy 初始化:是

是否多线程安全:是

实现难度:易

描述:这种方式具备很好的 lazy loading,能够在多线程中很好的工作,但是,效率很低,99% 情况下不需要同步。
优点:第一次调用才初始化,避免内存浪费。
缺点:必须加锁 synchronized 才能保证单例,但加锁会影响效率。
getInstance() 的性能对应用程序不是很关键(该方法使用不太频繁)。


/*** @author dustdawn* @date 2019/9/5 15:24*/
public class SingletonII {//懒汉构建单例模式private static SingletonII singletonII;private SingletonII() {}public  static synchronized SingletonII getInstance() {if (singletonII == null) {singletonII = new SingletonII();}return singletonII;}
}

静态内置类实现单例模式

登记式/静态内部类
是否 Lazy 初始化:是

是否多线程安全:是

实现难度:一般

描述:这种方式能达到双检锁方式一样的功效,但实现更简单。对静态域使用延迟初始化,应使用这种方式而不是双检锁方式。这种方式只适用于静态域的情况,双检锁方式可在实例域需要延迟初始化时使用。
这种方式同样利用了 classloader 机制来保证初始化 instance 时只有一个线程,它跟第 3 种方式不同的是:第 3 种方式只要 Singleton 类被装载了,那么 instance 就会被实例化(没有达到 lazy loading 效果),而这种方式是 Singleton 类被装载了,instance 不一定被初始化。因为 SingletonHolder 类没有被主动使用,只有通过显式调用 getInstance 方法时,才会显式装载 SingletonHolder 类,从而实例化 instance。想象一下,如果实例化 instance 很消耗资源,所以想让它延迟加载,另外一方面,又不希望在 Singleton 类加载时就实例化,因为不能确保 Singleton 类还可能在其他的地方被主动使用从而被加载,那么这个时候实例化 instance 显然是不合适的。这个时候,这种方式相比第 3 种方式就显得很合理。

/*** @author dustdawn* @date 2019/9/5 15:28*/
public class SingletonIII {//静态内置类实现单例模式private static class MySingleHandler {private static SingletonIII singletonIII = new SingletonIII();private MySingleHandler() {}public static SingletonIII getInstance() {return singletonIII;}}private SingletonIII() {}public static SingletonIII getInstance() {return MySingleHandler.getInstance();}
}

线程安全的单例模式: 双重检验锁(DCL)

双检锁/双重校验锁(DCL,即 double-checked locking)
JDK 版本:JDK1.5 起

是否 Lazy 初始化:是

是否多线程安全:是

实现难度:较复杂

描述:这种方式采用双锁机制,安全且在多线程情况下能保持高性能。
getInstance() 的性能对应用程序很关键。

/*** @author dustdawn* @date 2019/9/5 15:33*/
public class DCLSingleton {//双重校验锁实现线程安全的单例模式private static DCLSingleton dclSingleton = null;private DCLSingleton() {}public static DCLSingleton getInstance() {if (dclSingleton == null) {synchronized (DCLSingleton.class) {if (dclSingleton == null) {dclSingleton = new DCLSingleton();}}}return dclSingleton;}
}

原文地址


http://www.ngui.cc/el/2927065.html

相关文章

【算法】小米9.11笔试:《2048》

《2048》是一款热门的数字游戏。游戏中,每个方块上的数字都有2的幂,数字方块会根据指令整体进行上下左右移动,如果两个数字相同的方块在移动中碰撞,他们就会合成一个新的方块。例如下图为4*4格子的游戏,0表示格子为空&…

【剑指offer】斐波那契数列递归和非递归

package com.dust.acmcoder;/*** author dustdawn* date 2019/9/3 22:11*//*** 题目描述* 大家都知道斐波那契数列&#xff0c;现在要求输入一个整数n&#xff0c;请你输出斐波那契数列的第n项&#xff08;从0开始&#xff0c;第0项为0&#xff09;。** n<39*/ public class…

synchronized的线程安全实现

目录三个线程打印轮流ABC5次多线程下共享数据并发安全实现三个线程轮流打印A到Z用五个线程&#xff0c;顺序打印数字1~无穷大&#xff0c;其中每5个数字为1组百度百科&#xff1a; synchronized 关键字&#xff0c;代表这个方法加锁,相当于不管哪一个线程&#xff08;例…

try catch finally 的 ruturn 问题

直接上例子吧 public class test {public static String fun() {String result "hello";try {result "1";System.out.println("try");return result;} catch (Exception e) {result "2";System.out.println("catch");re…

Java反射API详解

反射 动态加载对象。在运行状态中&#xff0c;对于任何一个类&#xff0c;能够获取这个类的所有属性和方法&#xff0c;对于一个对象&#xff0c;能够调用它的的任意一个属性和方法&#xff0c;这种动态获取类的内容和动态调用对象的方法称为反射机制。 通过反射机制相关的API就…

Java2019秋招面试整理

文章目录JavaSEJre 和 Jdk 的区别?java 虚拟机 JVMJVM体系结构&#xff1a;GC垃圾回收站机制Java中的队和栈Java 程序运行机制Java 成员变量和局部变量变量的初始化引用数据类型基本数据类型基本数据类型转换之向上转型和向下转换方法的重载&#xff08;Overload&#xff09;操…

JavaEE2019秋招面试知识点整理

文章目录关系型数据库NoSQLRDBMS vs NoSQL分布式系统集群的优点ORMRedisIOC思想DIAOP事务JDBCJDBC连接池增强一个Java类中的某个方法有几种方式装饰设计模式装饰者模式(包装)数据库连接池&#xff1a;DBCP&#xff1a;C3P0&#xff1a;过滤器Filterfilter生命周期及其与生命周期…

Struts2学习笔记复习整理

文章目录概念优势Struts2历史AOP思想Struts2框架的搭建Struts2访问流程&Struts2架构配置详解核心配置struts.xmlstruts2常量配置修改struts2常量配置常用常量配置struts2配置进阶struts2的默认配置Action类详解Action方法结果跳转方式转发重定向转发到Action重定向到Action…

Spring复习整理

文章目录Spring介绍Spring优点Spring概念IOC思想DISpring AOP思想应用Spring底层实现:动态代理基于代理类的AOPAOP名词AspectJ开发Spring的核心容器BeanFactory(过时)ApplicationContextBeanFactory 和 ApplicationContext 的区别:Beanid 属性和 name 属性标签的配置scope 属性…

Mybatis复习面试整理

文章目录Mybatis介绍jdbc编程步骤&#xff1a;jdbc问题及Mybatis的解决&#xff1a;Mybatis架构#{}和${}parameterType和resultTypemysql自增主键返回mybatis与hibernate不同MyBatis动态代理原则配置SqlMapConfig.xmlMybatis介绍 Mybatis是一个支持普通SQL查询&#xff0c;存储…