Java设计模式(1)——单例模式

news/2025/2/19 8:02:30

一、单例模式

单例模式是Java设计模式中最简单的设计默认之一,其主要作用是用于维护全局单一示例对象。

  • 可以防止资源竞争
  • 用于维护全局单一对象,防止反复初始化。如配置、连接等。

设计关键点:

  • 构造函数private,保证只能通过类静态方法获取实例
  • 实例是静态对象,保证只被创建一次,线程安全

饿汉式

java">public class SingletonHungry {

    private static SingletonHungry INSTANCE = new SingletonHungry();

    private SingletonHungry() {

    }

    public static SingletonHungry getInstance() {
        return INSTANCE;
    }
}
  • 类加载时就INSTANCE对象被初始化,无法延迟初始化
  • 通过反射调用时会多次创建INSTANCE对象,

懒汉式

java">public class SingletonLazy {

    private static SingletonLazy instance;

    private SingletonLazy() {

    }

    public static synchronized SingletonLazy getInstance() {
        if (instance == null) {
            instance = new SingletonLazy();
        }
        return instance;
    }
}
  • getInstance时再对INSTANCE初始化,实现了懒加载。
  • 加锁保证线程安全,但是每次调用都需要加锁,性能低。

多重检测

java">public class SingletonDcl {
    private volatile static SingletonDcl instance; // 1

    private SingletonDcl () {

    }

    public static SingletonDcl getInstance() {
        if (instance == null) { // 2
            synchronized (SingletonDcl.class) { //3
                if (instance == null) { //4
                    instance = new SingletonDcl();
                }
            }
        }
        return instance;
    }
}
  • 1中的volatile关键字保证对象在new出来,并赋值给instance之后还没被初始化(执行构造函数),就被另一个对象使用(因为对象new操作和初始化操作不是原子操作)。不过只有很低很低的版本java才存在这个问题,现在jdk对象new操作和初始化操作已经被设计为原子操作。
  • 2的第一层判空保证在对象被new出来后,不再进入加锁逻辑,解决懒汉式性能低问题
  • 3锁定要锁定类对象,保证全局唯一性
  • 4的第二层判空为了解决如下问题:假设有两个线程A和B,都进行完第一次判空了,A和B都阻塞在synchronized位置,则A获得锁后new出对象释放锁,B再次获得锁后,需要判断A是否已经new过对象,否则就不能保证对象唯一。
  • 双重检查锁的这种单例模式性能比较高

静态内部类

java">public class SingletonInternal {

    private SingletonInternal() {

    }

    private static class SingletonHolder {
        private static final SingletonInternal INSTANCE = new SingletonInternal();
    }

    public static SingletonInternal getInstance() {
        return SingletonHolder.INSTANCE;
    }
}
  • SingletonInternal的加载不会初始化INSTANCE,这时与饿汉式的区别。只有通过显式调用 getInstance 方法时,才会显式装载 SingletonHolder 类,从而实例化 INSTANCE,实现了懒加载。

枚举

java">public enum Singleton {

    INSTANCE;

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

}
调用方法:

public class Main {

    public static void main(String[] args) {
        Singleton.INSTANCE.doSomething();
    }

}
  • 实现单例模式的最佳方法
  • 自动支持序列化机制,绝对防止多次实例化

http://www.niftyadmin.cn/n/876233.html

相关文章

java中的内部类与使用场景

java中的内部类java中的内部类成员内部类静态内部类局部内部类匿名内部类java中的内部类 java内部类分为:成员内部类、静态内部类、局部内部类、匿名内部类。 使用场景: 成员内部类:不想被其他类公开使用的类,因为外部类只能定…

zk报错:java.lang.IllegalStateException: Expected state [STARTED] was [LATENT]

zk报错:java.lang.IllegalStateException: Expected state [STARTED] was [LATENT] 原因: 客户端使用时没有start而直接调用了其他方法 解决办法: public CuratorFramework getCuratorFramework() throws InterruptedException {RetryPolicy retryPo…

IDEA运行报错:command line is too long. shorten command line

原因分析 出现此问题的直接原因是:IDEA集成开发环境运行你的“源码”的时候(注意是源码基础上运行,并非打好的jar包哦),是通过命令(首行那个非常非常长的)来启动Java进程的。这个命令主要包含两…

Zookeeper入门(2)——Curator介绍与引入

二、Curator介绍与引入 Apache Curator 1、Curator是什么? Apache Curator是Apache ZooKeeper的Java/JVM客户端库,这是一个分布式协调服务。它包括一个高级API框架和实用程序,使使用Apache ZooKeeper变得更容易和更可靠。它还包括常见用例和…

Zookeeper入门(3)——Leader选举与分布式锁

Leader选举与分布式锁Zookeeper客户端创建一、Leader选举1、获取领导权后不更换:使用示例测试2、感知领导权的变化:二、分布式锁1、可重入独占锁InterProcessMutexInterProcessMutex实现原理InterProcessMutex常用方法使用示例2、读写锁InterProcessRead…

排序算法专题——数组链表排序

排序算法专题 数组排序 快速排序 每次partition之后,partition的节点位置已经定好,需要对[start, partition-1] 和[partition 1, end]再排序如果start > end后跳出循环,说明排序结束 class Demo{private int randomIndex(int start, …

Mysql8数据库如何给用户授权

查看用户已有权限 SHOW GRANTS FOR [用户名];使用root用户授予所有权限 -- 授权 GRANT ALL PRIVILEGES ON [数据库名].[表明] TO [用户名][连接地址] WITH GRANT OPTION; -- 刷新权限 FLUSH PRIVILEGES;例如给numb用户的所有连接地址授权numb数据库所有表权限如下&#xff1a…

MySQL学习笔记(3)——MySQL的索引

三、MySQL的索引三、MySQL的索引1、MySQL索引的类型主要有哪些_?2、常见存储引擎与其支持的索引?3、MyIASM与InnoDB的B-Tree索引区别4、如何创建一个B-Tree索引4.1 建表时新建索引4.2 建表后新增索引4.3 删除索引5、KEY与INDEX关键字的区别5.1 KEY关键字…