首页 > 编程语言 >JAVA 单例模式 饿汉和懒汉

JAVA 单例模式 饿汉和懒汉

时间:2022-12-12 21:55:42浏览次数:71  
标签:JAVA 饿汉 private instance 实例 static 单例

单例模式特点:
① 单例类只能有一个实例
② 私有构造方法,不允许通过其他类创建单例类的实例
③ 提供静态get方法返回单实例

饿汉式:类加载的时候就创建实例
懒汉式:类加载时不创建实例,第一次调用get方法时才创建实例

饿汉式优点:简单,调用时速度快,无需考虑创建实例时线程安全问题
饿汉式缺点:占用内存,可能使用该类时只使用了其静态方法,却创建了对象

懒汉式优点:第一次获取实例前占用内存少
懒汉式缺点:需要考虑线程安全,第一次获取实例时要进行初始化工作

饿汉式:

/**
 * 饿汉单例模式
 * 类加载的时候就创建实例
 */
public class SingleInstance1 {
    private static final SingleInstance1 instance = new SingleInstance1();

    //构造方法要私有
    private SingleInstance1() {
        System.out.println("SingleInstance1 实例化了一个单例对象");
    }

    public static SingleInstance1 getInstance() {
        return instance;
    }
}

volatile 关键字:禁止指令重排序(防止虚拟机先分配地址后初始化对象)、对缓存的修改立即写入主存、阻止其他线程对其进行写操作
双重检查锁定:如果同步块中不再次判断是否为null可能会实例化两次。如果两个线程同时执行完成第一个if,其中一个获得锁并实例化了对象,然后另一个线程进入同步块不会再次判断是否为null,而再次实例化。

懒汉式:使用 synchronized

/**
 * 懒汉单例模式
 * 初始时不创建实例,第一次调用get方法时才创建实例
 */
public class SingleInstance2 {
    //使用 volatile 修饰单实例
    private volatile static SingleInstance2 instance;

    //构造方法要私有
    private SingleInstance2() {
    }

    public static SingleInstance2 getInstance() {
        if (instance == null) {
            synchronized (SingleInstance2.class) {
                if (instance == null) {
                    instance = new SingleInstance2();
                    System.out.println("SingleInstance2 实例化了一个单例对象");
                }
            }
        }
        return instance;
    }
}

懒汉式:使用 ReentrantLock

/**
 * 懒汉单例模式
 * 初始时不创建实例,第一次调用get方法时才创建实例
 */
public class SingleInstance3 {
    //使用 volatile 修饰单实例
    private volatile static SingleInstance3 instance;
    private static ReentrantLock lock = new ReentrantLock();

    //构造方法要私有
    private SingleInstance3() {
    }

    public static SingleInstance3 getInstance() {
        if (instance == null) {
            lock.lock();
            try {
                if (instance == null) {
                    instance = new SingleInstance3();
                    System.out.println("SingleInstance3 实例化了一个单例对象");
                }
            } finally {
                lock.unlock();
            }
        }
        return instance;
    }
}

静态内部类方式

双重检查太麻烦?可以用静态内部类方式。

任意类都只会被加载一次,其中的静态代码块也只会执行一次,保证是单例。
内部类不被调用时不会加载,即饿汉式,避免创建无用单例浪费内存空间。
类加载过程是线程安全的,所以无需双重检查。
内部类可以访问外部类所有方法,包括私有的构造方法
内部类必须私有化,不允许被修改,由外部类提供获取单例的方法

public class Singleton {
    // 私有化构造方法
    private Singleton() {};

    // 私有静态内部类
    private static class SingletonHolder {
        private static Singleton instance;
        
        static {
            instance = new Singleton();
            System.out.println("单例对象被实例化了");
        }
    }

    // 获取单例
    public static Singleton getInstance() {
        return SingletonHolder.instance;
    }
}

 



标签:JAVA,饿汉,private,instance,实例,static,单例
From: https://www.cnblogs.com/shoshana-kong/p/16977212.html

相关文章

  • Java实现LRU算法
    文章目录1、内存空间有限,当缓存满的时候,如何淘汰缓存?2、实现LRUdemo使用Java容器LinkedHashMap哈希表(HashMap)+双向链表 1、内存空间有限,当缓存满的时候,如何淘汰缓......
  • Java实现二叉树的先序、中序、后序、层序遍历(递归+非递归方法),附带自己深入浅出的讲解
     二叉树(Binarytree)是树形结构的一个重要类型,也一种非常重要的数据结构,更是算法题中高频出现的知识点,不管是为了应付工作还是面试,都有必要深度学习一下。二叉树有多种遍......
  • java学习笔记--java介绍,一些基本知识,面向对象的理解
    <1>Java介绍1)Java的特点简单易学    是c和c++的变种,而且摒弃了其中容易引起程序错误的地方,比如结构体,内存回收等。提供了丰富的类库。完全面向对象。安全性高......
  • JavaScript奇淫技巧:用密码保护你的照片
    JavaScript奇淫技巧:密码保护的私密图片JavaScript奇淫技巧:图片压缩、图片加密本文将用JavaScript实现两个颇有技术含量的功能:图片压缩、图片加密。最终效果:可实现将任意图片......
  • 小新学Java18-【函数式接口】
    一、函数式接口1.1概念1.2格式1.3@FunctionalInterface注解@FunctionalInterface注解作用:可以检测接口是否是一个函数式接口是:编译成功否:编......
  • java环境搭建安装
    2.java环境搭建安装2.1JDK下载​开发人员要进行开发需要安装jdk,程序运行的话环境只需要jre,所以我们作为开发人员,需要下载jdk,最新版本为jdk17,下载地址为oracle官......
  • Java大型建筑建设综合工程项目管理系统源码带原生APP源码 工程管理系统源码带操作手册
    客户端下载:1、安卓手机端先下载“PP助手”应用商店,再在PP助手中搜索“star工程”下载安装。2、苹果手机端苹果手机APPstore中搜索“star工程”下载安装。建设综合工程......
  • 【校招VIP】线上实习 推电影 电影详情模块 Java文档周最佳
    【推电影】主要是为校招设计的年青人电影推荐平台项目,每个模块都具有亮点和难点,项目表现为手机网站应用,可嵌入小程序或APP中。恭喜来自南京邮电大学的日月同辉同学获得本......
  • day01-java流程
    Scanner对象基本语法:Scanners=newScanner(System.in);next()方法nextLine()方法顺序结构选择结构if单选结构语法:if(布尔表达式){//如果布尔表达式为true将......
  • JAVA基础
    JAVA基础注释注释不会被执行,是给写代码的人看的单行注释://多行注释:/**/(快捷键:选中->ctrl+shift+/;/*+回车)文档注释(JavaDoc)(快捷键:/**+回车)......