原创文章,转载请标注出处:https://www.cnblogs.com/V1haoge/p/10755322.html

一、概述

Java中单例有7种写法,这个是在面试中经常被问到的内容,而且有时候还要求手写单例实现方式。所以我们有必要认真的了解一下这七种写法。

二、七种实现

2.1 懒汉式——线程不安全

public class SingletonOne {
public static SingletonOne singleton;
private SingletonOne() {}
public static SingletonOne getSingleton() {
if (singleton == null)
return new SingletonOne();
return singleton;
}
}

懒汉式实现了懒加载,但是线程不安全,基本不会使用。

2.2 懒汉式——线程安全

public class SingletonTwo {
public static SingletonTwo singleton;
private SingletonTwo() {}
public static synchronized SingletonTwo getSingleton() {
if (singleton == null)
return new SingletonTwo();
return singleton;
}
}

在第一种的基础上加了个synchronized,保证线程安全,同时实现了懒加载,只是效率不高。

2.3 饿汉式

public class SingletonThree {
public static SingletonThree singleton = new SingletonThree();
private SingletonThree () { }
public static SingletonThree getSingleton() {
return singleton;
}
}

由于实例优先提供,不存在线程安全问题,但是没有实现懒加载。

2.4 饿汉式——变种

public class SingletonFour {
public static SingletonFour singleton;
static {
singleton = new SingletonFour();
}
private SingletonFour () { }
public static SingletonFour getSingleton() {
return singleton;
}
}

其实和之前的一样,仅仅是将单例的创建挪到了静态块。

2.5 静态内部类式

public class SingletonFive {
private static class SingletonHolder {
private static SingletonFive singleton = new SingletonFive();
}
private SingletonFive () {}
public static final SingletonFive getSingleton(){
return SingletonHolder.singleton;
}
}

静态内部类保证了懒加载,单例实例优先提供又保证了线程安全性,较实用。

2.6 枚举式

public enum SingletonSix {
SINGLETON;
}

枚举的天然特性保证了单例,天然的私有构造器,天然的线程安全性,未被大规模使用的原因是枚举出现的有点晚。

2.7 双重校验锁式

public class SingletonSeven {
private static volatile SingletonSeven singleton;
private SingletonSeven() {}
public static SingletonSeven getSingleton(){
if (singleton == null) {
synchronized (SingletonSeven.class) {
if (singleton == null)
return new SingletonSeven(); }
}
return singleton;
}
}

注意:

  1. volatile的使用,为了防止暴露一个未初始化的不完整单例实例;
  2. 双重判空校验,第一个判断避免了频繁的加锁,第二个判断可以拦住多余的创建实例的线程;
  3. 加锁,保证了线程安全(只有一个实例)

这种实现方式是经常出现在面试题中的,而且经常会要求手写。

三、总结

上面罗列的7种设计模式中第1种线程不安全,可以排除在外,第3、4种其实是一种,这样下来其实可以简化为5种方式:懒汉、饿汉、静态内部类、枚举、双重校验锁。

Java基础系列-单例的7种写法的更多相关文章

  1. 转载:java基础之单例

    转载:https://blog.csdn.net/goodlixueyong/article/details/51935526 https://www.cnblogs.com/cielosun/p/6 ...

  2. Java并发编程中的设计模式解析(二)一个单例的七种写法

    Java单例模式是最常见的设计模式之一,广泛应用于各种框架.中间件和应用开发中.单例模式实现起来比较简单,基本是每个Java工程师都能信手拈来的,本文将结合多线程.类的加载等知识,系统地介绍一下单例模 ...

  3. java基础28 单例集合Collection下的List和Set集合

    单例集合体系: ---------| collection  单例集合的根接口--------------| List  如果实现了list接口的集合类,具备的特点:有序,可重复       注:集合 ...

  4. java基础27 单例集合Collection及其常用方法

    1.集合 集合是存储对象数据的集合容器 1.1.集合比数组的优势 1.集合可以存储任意类型的数据,数组只能存储同一种数据类型的数据    2.集合的长度是变化的,数组的长度是固定的 1.2.数组:存储 ...

  5. java单例的几种写法

    转载出处:http://cantellow.javaeye.com/blog/838473 第一种(懒汉,线程不安全): public class Singleton { private static ...

  6. 「Android」单例的五种写法

    单例 发现博客园可以很好的设置自己的博客文章的展示,很开心,然后特此发一篇 其实这几种写法大家应该都会的,就权当拿来记录一下吧,以后复习巩固也比较方便. 这篇文章中的代码,来自一篇视频(我想找视频贴上 ...

  7. java23种设计模式之二: 单例设计模式(6种写法)

    目的:在某些业务场景中,我们需要某个类的实例对象的只能有一个,因此我们需要创建一些单例对象. 本文共有6种写法,仅供参考 1.饿汉式 优点: 在多线程情况下,该方法创建的单例是线程安全的(立即加载) ...

  8. .NET Core中延迟单例另一种写法【.NET Core和.NET Framework的beforefieldinit差异】

    1.BeforeFieldInit是什么 前段时间在反编译代码时无意间看到在类中有一个BeforeFieldInit特性,处于好奇的心态查了查这个特性,发现这是一个关于字段初始化时间的特性[提前初始化 ...

  9. java单例的几种实现方法

    java单例的几种实现方法: 方式1: public class Something { private Something() {} private static class LazyHolder ...

随机推荐

  1. Lyndon Word相关

    Lyndon Word 定义 对于字符串 \(S\),若 \(S\) 的最小后缀为其本身,那么称 \(S\) 为 \(\text{Lyndon}\) 串(\(\text{Lyndon Word}\)) ...

  2. 最全153道Spring全家桶面试题,你都碰到过哪些?(含答案解析)

    前言 Spring 框架自诞生以来一直备受开发者青睐,有人亲切的称之为:Spring 全家桶. 毋庸置疑,Spring 早已成为 Java 后端开发的行业标准,无数的公司选择 Spring 作为基础的 ...

  3. Spring的BeanFactory是什么?

    什么是BeanFactory? 提到Spring,总是让人第一时间想起IOC容器,而IOC容器的顶层核心接口就是我们的BeanFactory,如果能够理解BeanFactory的体系结构想必能让我们对 ...

  4. CPU 执行程序的秘密,藏在了这 15 张图里

    前言 代码写了那么多,你知道 a = 1 + 2 这条代码是怎么被 CPU 执行的吗? 软件用了那么多,你知道软件的 32 位和 64 位之间的区别吗?再来 32 位的操作系统可以运行在 64 位的电 ...

  5. Angluar2 项目搭建

    一 使用 Angular CLI 官方脚手架 1.安装 cli npm install -g @angular/cli 2.创建工作空间和初始应用 ng new my-app 二 tsLint 代码格 ...

  6. eclipse 配置opencv

    1 准备 eclipse 2017 JDK1.8 opencv 4.40 2 配置 新建java工程 添加jar包 选择opencv-xxx.jar包 加入原生库 选择原生库位置 确认即可,测试 新建 ...

  7. C#使用RabbitMq队列(Sample,Work,Fanout,Direct等模式的简单使用)

    1:RabbitMQ是个啥?(专业术语参考自网络) RabbitMQ是实现了高级消息队列协议(AMQP)的开源消息代理软件(亦称面向消息的中间件). RabbitMQ服务器是用Erlang语言编写的, ...

  8. 联赛模拟测试18 A. 施工 单调队列(栈)优化DP

    题目描述 分析 对于 \(Subtask\ 1\),可以写一个 \(n^3\) 的 \(DP\),\(f[i][j]\) 代表第 \(i\) 个建筑高度为 \(j\) 时的最小花费,随便转移即可 时间 ...

  9. oh my zsh 安装

    date: "2020-10-18T12:36:00+08:00" title: "oh my zsh 安装" tags: ["zsh",& ...

  10. centos8上安装mysql8

    一,下载并解压mysql8 1,mysql官网 https://www.mysql.com/ 2,下载到source目录 [root@yjweb source]# wget https://cdn.m ...