设计模式之——单例模式

前言

单例模式是在面试中是最容易被考到的设计模式,这是因为单例模式是设计模式中最简单的,几行代码就能搞定(现场手写代码);同时单例模式又有多种实现方式,涉及到线程安全、懒加载、序列化等问题。

单例模式一共分为5种:

  1. Eager initialization(饿汉模式)
  2. Lazy initialization(懒汉模式)
  3. double-checked locking(双重加锁)
  4. Initialization-on-demand holder idiom(静态内部类)
  5. The enum way(枚举)

设计模式之——Singleton pattern

饿汉模式

代码

// 饿汉模式,开始就创建实例,线程安全
public class Wife1 {
    
    private static final Wife1 wife = new Wife1();
    
    private Wife1() {}
    
    public static Wife1 getWife() {
        return wife;
    }
}

说明

  1. 在类加载之后、被任何线程使用之前,static 的变量 INSTANCE 就已经定义好。
  2. 方法getInstance()不需要同步,所有的线程都会看到同样的实例。
  3. 关键字final使得 INSTANCE 不能修改,保证有且只有一个实例。

懒汉模式

代码

// 懒汉模式,需要时才创建实例,需加锁
public class Wife2 {
    private static Wife2 wife;
    
    private Wife2() {}
    
    public static synchronized Wife2 getWife() {
        if (wife == null) {
            wife = new Wife2();
        }
        return wife;
    }
}

说明

  1. 获得实例方法是线程同步的,效率低

双重加锁

代码

// 双重加锁,通过volatile关键字防止编译器重排序,Java 1.5以下不可用
public class Wife3 {
    private volatile static Wife3 wife;
    
    private Wife3() {}
    
    public static synchronized Wife3 getWife() {
        if (wife == null) {
            synchronized (Wife3.class) {
                if (wife == null) {
                    wife = new Wife3();
                }
            }
        }
        return wife;
    }
}

说明

  1. 只有在第一次时,才会同步类,效率高
  2. volatile关键字,在Java 1.5以下不可用

静态内部类

代码

// 静态内部类
public class Wife4 {
    
    // 只有在需要时,才被JVM加载。加载类Wife4时,不加载内部类WifeHolder
    private static class WifeHolder {
        private static final Wife4 wife = new Wife4();
    }
    
    private Wife4() {}
    
    public static Wife4 getWife() {
        return WifeHolder.wife;
    }
}

说明

  1. 尽可能延迟加载
  2. 适用于所有的Java版本
  3. 线程安全

枚举

代码

// 枚举,《Effective Java》推荐方法,最简单、线程安全
public enum Wife5 {
    INSTANCE;
}

说明

  1. 实现极其简单
  2. Java 1.5及以上
  3. 线程安全

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

相关文章

来自专栏技术之路

设计模式:单例模式

今天来简单来说一下单例模式:它要确保一个类只有一个实例,而且自行实例化并向整个系统提供这个实例。 比如我们登录一个系统的时候要记录一个员工的信息,在整个系统运行...

2228
来自专栏数据之美

关于 MySQL UTF8 编码下生僻字符插入失败/假死问题的分析

1、问题:mysql 遇到某些中文插入异常 最近有同学反馈了这样一个问题: ? 上述语句在脚本中 load 入库的时候会 hang 住,web 前端、命令行操作...

4319
来自专栏林德熙的博客

C# BBcode 转 Markdown

本文的方法都是使用正则转换,现在支持的代码只有很少的常用标签,如果大家发现有转换失败的,请帮我修改代码,估计代码我不会进行修改。

571
来自专栏数据结构与算法

BZOJ5312: 冒险(势能均摊线段树)

结论:如果一次操作对区间& 和 区间| 产生的影响是相同的,那么该操作对整个区间的影响都是相同的

1032
来自专栏IT笔记

Python3中文字符编码问题

最近在尝试 Python Web方面的开发尝试,框架使用的是Django,但是在读取数据库并页面展示的时候,出现了中文编码的问题。

4423
来自专栏王亚昌的专栏

类静态指针的申请和释放

     如果类有一个静态成员指针变量,在进程中执行new或malloc操作分配了内存,进程退出前并不需要调用new或malloc,因为系统会自动进行释放。但这...

1062
来自专栏数据分析

SQL Server 性能优化之——T-SQL NOT IN 和 NOT Exists

这次介绍一下T-SQL中“Not IN” 和“Not Exists”的优化。 Not IN 和 Not Exists 命令 : 有些情况下,需要select/u...

3617
来自专栏cs

python文件

4617
来自专栏浪淘沙

java实现输出文件夹下某个格式的所有文件

1081
来自专栏魏琼东

基于DotNet构件技术的企业级敏捷软件开发平台 - AgileEAS.NET - 数据关系映射ORM

      上一遍我介绍了AgileEAS.NET中统计的数据访问,本文我将来介绍AgileEAS.NET中的ORM实现思路。关于ORM的概念和介绍,我在此就不...

2078

扫码关注云+社区

领取腾讯云代金券