详解Java中的八种单例创建方式

目录
  • 定义
  • 使用场景
  • 单例模式八种方式
    • 饿汉式(静态常量)
    • 饿汉式(静态代码块)
    • 懒汉式(线程不安全)
    • 懒汉式(同步方法)
    • 懒汉式(同步代码块)
    • 双重检查锁方式
    • 静态内部类方式
    • 枚举方式
  • 总结

定义

单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法)

使用场景

  • 对于一些需要频繁创建销毁的对象
  • 重量级的对象
  • 经常使用到的对象
  • 工具类对象
  • 数据源
  • session

单例模式八种方式

饿汉式(静态常量)

代码

/**
 * 饿汉式(静态常量)
 * 优势:简单,避免多线程的同步问题
 * 劣势:无懒加载,内存浪费
 * @author:liyajie
 * @createTime:2022/2/10 15:50
 * @version:1.0
 */
public class Singleton1 {
    // 私有化构造方法
    private Singleton1(){}

    // 静态常量
    private static final Singleton1 singleton1 = new Singleton1();

    // 对外提供公共方法
    public static Singleton1 getSingleton1(){
        return singleton1;
    }
}

分析

  • 优势:简单,避免多线程的同步问题
  • 劣势:无懒加载,内存浪费

饿汉式(静态代码块)

代码

/**
 * 饿汉式(静态代码块)
 * 优势:简单,避免多线程的同步问题
 * 劣势:无懒加载,内存浪费
 * @author:liyajie
 * @createTime:2022/2/10 15:50
 * @version:1.0
 */
public class Singleton2 {
    // 私有化构造方法
    private Singleton2(){}

    private static final Singleton2 singleton2;

    // 静态代码块
    static {
        singleton2 = new Singleton2();
    }

    // 对外提供公共方法
    public static Singleton2 getSingleton2(){
        return singleton2;
    }
}

分析

  • 优势:简单,避免多线程的同步问题
  • 劣势:无懒加载,内存浪费

懒汉式(线程不安全)

代码

/**
 * 懒汉式(线程不安全)
 * @author:liyajie
 * @createTime:2022/2/10 15:50
 * @version:1.0
 */
public class Singleton3 {
    // 私有化构造方法
    private Singleton3(){}

    // 内部属性
    private static Singleton3 singleton3;

    // 对外提供公共方法
    public static Singleton3 getSingletons(){
        if(singleton3 == null){
            singleton3 = new Singleton3();
        }
        return singleton3;
    }
}

分析

  • 优势:起到了懒加载的效果 不会造成内存浪费
  • 劣势:线程不安全 不推荐这种方式的

懒汉式(同步方法)

代码

/**
 * 懒汉式(同步方法)
 * 优势:解决了线程同步问题
 * 劣势:使用synchronized同步关键字,性能太低
 * @author:liyajie
 * @createTime:2022/2/10 15:50
 * @version:1.0
 */
public class Singleton4 {
    // 私有化构造方法
    private Singleton4(){}

    // 内部属性
    private static Singleton4 singleton4;

    // 对外提供公共方法
    public static synchronized Singleton4 getSingleton4(){
        if(singleton4 == null){
            singleton4 = new Singleton4();
        }
        return singleton4;
    }
}

分析

  • 优势:解决了线程安全问题,
  • 劣势:效率太低

懒汉式(同步代码块)

代码

/**
 * 懒汉式(同步代码块)
 * @author:liyajie
 * @createTime:2022/2/10 15:50
 * @version:1.0
 */
public class Singleton5 {
    // 私有化构造方法
    private Singleton5(){}

    // 内部属性
    private static Singleton5 singleton5;

    // 对外提供公共方法
    public static Singleton5 getSingleton5(){
        if (singleton5 == null){
            synchronized (Singleton5.class){
                singleton5 = new Singleton5();
            }
        }
        return singleton5;
    }
}

分析

  • 优势:起到了懒加载的效果 不会造成内存浪费
  • 劣势:线程不安全 不推荐这种方式的

双重检查锁方式

代码

/**
 * 双重检查锁机制
 * @author:liyajie
 * @createTime:2022/2/10 15:50
 * @version:1.0
 */
public class Singleton6 {
    // 私有化构造方法
    private Singleton6(){}

    // 内部属性
    private volatile static Singleton6 singleton6;

    // 对外提供公共方法
    public static Singleton6 getSingleton6(){
        if (singleton6 == null){
            synchronized (Singleton6.class){
                if(singleton6 == null){
                    singleton6 = new Singleton6();
                }
            }
        }
        return singleton6;
    }
}

分析

  • 实现了懒加载,效率很高,解决了线程安全

静态内部类方式

代码

/**
 * 静态内部类
 * @author:liyajie
 * @createTime:2022/2/10 15:50
 * @version:1.0
 */
public class Singleton7 {
    // 私有化构造方法
    private Singleton7(){}

    // 内部类
    private static class SingleInstance{
        public static final Singleton7 singleton7 = new Singleton7();
    }

    // 对外提供公共方法
    public static Singleton7 getSingleton7(){
        return SingleInstance.singleton7;
    }
}

分析

  • 不会出现线程安全问题 JVM来帮我们保证了线程的安全性
  • 利用静态内部类的特点,效率也很高,
  • 实际开发中推荐使用的

枚举方式

代码

定义单例对象

/**
 * @desc:
 * @author:liyajie
 * @createTime:2022/2/11 10:25
 * @version:1.0
 */
public class Singleton {

    public void hello(){
        System.out.println("hello");
    }
}

定义枚举实例化单例对象

/**
 * 枚举方式
 * @author:liyajie
 * @createTime:2022/2/10 15:50
 * @version:1.0
 */
enum Singleton8 {
    // 相当于public static final Singleton8 INSTANCE;
    // 保证了枚举实例只能被实例化一次
    INSTANCE;

    // 定义单例变量
    private Singleton singleton;

    // 枚举构造方法,该构造方法是private,执行构造方法的时候,同时创建我们的单例对象
    Singleton8() {
        singleton = new Singleton();
    }

    // 对外提供公共方法
    public Singleton getSingleton() {
        return singleton;
    }
}

使用方法Singleton8.INSTANCE.getSingleton()即可获取我们的单例对象了

分析

  • 简单,避免了线程安全问题
  • 实际开发中推荐使用的

总结

1.单例模式保证了系统内存中该类只存在一个对象,节省了系统资源,对于一些需要频繁创建销毁的对象, 使用单例模式可以提高系统性能

2.当想实例化一个单例类的时候,必须要记住使用相应的获取对象的方法,而不是使用new

3.单例模式推荐使用的方法有内部静态类方式和枚举方式

到此这篇关于详解Java中的八种单例创建方式的文章就介绍到这了,更多相关Java单例创建方式内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java单例模式实现的几种方式

    Java单例模式实现的几种方式 单例模式好多书上都是这么写的: public class SingleTon1 { private SingleTon1(){ } private static SingleTon1 instance = null; public static SingleTon1 getInstance(){ if(instance == null){ instance = new SingleTon1(); } return instance; } } 但是实际开发中是不会这

  • java 单例的五种实现方式及其性能分析

    java 单例的五种实现方式及其性能分析 序言 在23种设计模式中,单例是最简单的设计模式,但是也是很常用的设计模式.从单例的五种实现方式中我们可以看到程序员对性能的不懈追求.下面我将分析单例的五种实现方式的优缺点,并对其在多线程环境下的性能进行测试. 实现 单例模式适用于资源占用较多的类,保证一个类只有一个实例即单例.通用的做法就是构造器私有化,提供一个全局的访问点,返回类的实例. uml图: 1.饿汉式 代码实现: package com.zgh.gof23.singleton; /** *

  • JAVA设计模式零基础解析之单例模式的八种方式

    目录 单例模式简介: 单例模式优点: 应用场景: 单例设计模式的八种方式: 1.饿汉式(静态常量) 2.饿汉式(静态代码块) 3.懒汉式(线程不安全) 4.懒汉式(线程安全,同步方法) 5.懒汉式(线程安全,同步代码块) 6.双重检查(推荐使用) 7.静态内部类(推荐使用) 8.枚举(推荐使用) 单例模式在JDK应用的源码分析 单例模式注意事项和细节说明 单例模式简介: 单例模式(Singleton Pattern)是 Java 中最简单的设计模式之一.这种类型的设计模式属于创建型模式,它提供了

  • 详解Java实现单例的五种方式

    1. 什么是单例模式 单例模式指的是在应用整个生命周期内只能存在一个实例.单例模式是一种被广泛使用的设计模式.他有很多好处,能够避免实例对象的重复创建,减少创建实例的系统开销,节省内存. 单例模式的要求有三点: 某个类只能有一个实例 它必须自行创建这个实例 他必须自行向整个系统提供整个实例 2. 单例模式和静态类的区别 首先理解一下什么是静态类,静态类就是一个类里面都是静态方法和静态field,构造器被private修饰,因此不能被实例化.Math类就是一个静态类. 知道了什么是静态类后,来说一

  • Java单例模式的6种实现方式详解

    目录 为什么使用单例模式 使用单例模式需要注意的关键点 单例模式的几种写法 1. 饿汉式 2. 懒汉式 3. DCL(Double CheckLock)实现单例 4. 静态内部类 5. 枚举单例 6. 容器实现单例 总结 为什么使用单例模式 需要确保某个类只要一个对象,或创建一个类需要消耗的资源过多,如访问IO和数据库操作等,这时就需要考虑使用单例模式了. 使用单例模式需要注意的关键点 将构造函数访问修饰符设置为private 通过一个静态方法或者枚举返回单例类对象 确保单例类的对象有且只有

  • 分析java中全面的单例模式多种实现方式

    一.单例模式的思想 想整理一些 java 并发相关的知识,不知道从哪开始,想起了单例模式中要考虑的线程安全,就从单例模式开始吧.以前写过单例模式,这里再重新汇总补充整理一下,单例模式的多种实现. 单例模式的主要思想是: 将构造方法私有化( 声明为 private ),这样外界不能随意 new 出新的实例对象: 声明一个私有的静态的实例对象,供外界使用: 提供一个公开的方法,让外界获得该类的实例对象 这种说法看上去没错,但也好像不太准确.其实,就算外界能随意 new 出新的实例对象,但只要我们保证

  • JAVA破坏单例模式的方式以及避免方法

    单例模式,大家恐怕再熟悉不过了,其作用与实现方式有多种,这里就不啰嗦了.但是,咱们在使用这些方式实现单例模式时,程序中就真的会只有一个实例吗? 聪明的你看到这样的问话,一定猜到了答案是NO.这里笔者就不卖关子了,开门见山吧!实际上,在有些场景下,如果程序处理不当,会无情地破坏掉单例模式,导致程序中出现多个实例对象. 下面笔者介绍笔者已知的三种破坏单例模式的方式以及避免方法. 1.反射对单例模式的破坏 我们先通过一个例子,来直观感受一下 (1)案例 DCL实现的单例模式: public class

  • 详解Java中的八种单例创建方式

    目录 定义 使用场景 单例模式八种方式 饿汉式(静态常量) 饿汉式(静态代码块) 懒汉式(线程不安全) 懒汉式(同步方法) 懒汉式(同步代码块) 双重检查锁方式 静态内部类方式 枚举方式 总结 定义 单例设计模式,就是采取一定的方法保证在整个的软件系统中,对某个类只能存在一个对象实例,并且该类只提供一个取得其对象实例的方法(静态方法) 使用场景 对于一些需要频繁创建销毁的对象 重量级的对象 经常使用到的对象 工具类对象 数据源 session 单例模式八种方式 饿汉式(静态常量) 代码 /**

  • 详解java中的6种单例写法及优缺点

    在java中,单例有很多种写法,面试时,手写代码环节,除了写算法题,有时候也会让手写单例模式,这里记录一下单例的几种写法和优缺点. 1.初级写法 2.加锁 3.饿汉式 4.懒汉式 5.双锁检验 6.内部类 1.初级写法 package com.java4all.test6; /** * Author: yunqing * Date: 2018/8/13 * Description:单例模式 -- 初级 */ public class Singleton { private static Sing

  • 详解java中的四种代码块

    在java中用{}括起来的称为代码块,代码块可分为以下四种: 一.简介 1.普通代码块: 类中方法的方法体 2.构造代码块: 构造块会在创建对象时被调用,每次创建时都会被调用,优先于类构造函数执行. 3.静态代码块: 用static{}包裹起来的代码片段,只会执行一次.静态代码块优先于构造块执行. 4.同步代码块: 使用synchronized(){}包裹起来的代码块,在多线程环境下,对共享数据的读写操作是需要互斥进行的,否则会导致数据的不一致性.同步代码块需要写在方法中. 二.静态代码块和构造

  • 详解Java中的三种流程控制语句

    目录 顺序语句 选择语句 if else的嵌套 switch case default 循环语句 for for in while do while break continue 顺序语句 顺序顾名思义就是程序自上而下执行 public class User { public static void main(String[] args) { String name = "hacker"; int age = 18; String happy = "学习Java";

  • 详解Java 中的三种代理模式

    代理模式 代理(Proxy)是一种设计模式,提供了对目标对象另外的访问方式;即通过代理对象访问目标对象.这样做的好处是:可以在目标对象实现的基础上,增强额外的功能操作,即扩展目标对象的功能. 这里使用到编程中的一个思想:不要随意去修改别人已经写好的代码或者方法,如果需改修改,可以通过代理的方式来扩展该方法. 举个例子来说明代理的作用:假设我们想邀请一位明星,那么并不是直接连接明星,而是联系明星的经纪人,来达到同样的目的.明星就是一个目标对象,他只要负责活动中的节目,而其他琐碎的事情就交给他的代理

  • 详解Java中Period类的使用方法

    目录 简介 Duration和Period 创建方法 通过时间单位创建 通过LocalDate创建 解析方法 比较方法 增减方法 转换单位 取值方法 简介 本文用示例介绍java的Period的用法. Duration和Period 说明 Duration类通过秒和纳秒相结合来描述一个时间量,最高精度是纳秒.时间量可以为正也可以为负,比如1天(86400秒0纳秒).-1天(-86400秒0纳秒).1年(31556952秒0纳秒).1毫秒(0秒1000000纳秒)等. Period类通过年.月.日

  • 详解Java中Duration类的使用方法

    目录 简介 Duration和Period 创建方法 通过时间单位创建 通过LocalDateTime或LocalTime 通过已有的Duration 解析方法 用法说明 详解 比较方法 增减方法 转换单位 取值方法 简介 本文用示例介绍java的Duration的用法. Duration和Period 说明 Duration类通过秒和纳秒相结合来描述一个时间量,最高精度是纳秒.时间量可以为正也可以为负,比如1天(86400秒0纳秒).-1天(-86400秒0纳秒).1年(31556952秒0纳

  • 详解Java中数组判断元素存在几种方式比较

    1. 通过将数组转换成List,然后使用List中的contains进行判断其是否存在 public static boolean useList(String[] arr,String containValue){ return Arrays.asList(arr).contains(containValue); } 需要注意的是Arrays.asList这个方法中转换的List并不是java.util.ArrayList而是java.util.Arrays.ArrayList,其中java.

  • 详解Java中两种分页遍历的使用姿势

    在日常开发中,分页遍历迭代的场景可以说非常普遍了,比如扫表,每次捞100条数据,然后遍历这100条数据,依次执行某个业务逻辑:这100条执行完毕之后,再加载下一百条数据,直到扫描完毕 那么要实现上面这种分页迭代遍历的场景,我们可以怎么做呢 本文将介绍两种使用姿势 常规的使用方法 借助Iterator的使用姿势 1. 数据查询模拟 首先mock一个分页获取数据的逻辑,直接随机生成数据,并且控制最多返回三页 public static int cnt = 0; private static List

  • Java详解Swing中的几种常用按钮的使用

    目录 Swing中的常用按钮 AbstractButton的常用方法 JRadionButton(单选按钮) 单选按钮的构造方法 复选框(JCheckBox) 复选框的构造方法 组合框(JComboBox) 组合框的构造方法 下拉列表框的常用方法 小结 Swing中的常用按钮 在Swing中,常见的按钮组件有JButton,JCheckBox,JRadioButton等,它们都是抽象类AbstractButton类的直接或间接子类.在AbstractButton类中提供了按钮组件通用的一些方法.

随机推荐