Java单例模式的几种实现
转载请注明原文地址:https://www.cnblogs.com/ygj0930/p/10845530.html
一:静态内部类实现单例模式
原理:通过一个静态内部类定义一个静态变量来持有当前类实例,在类加载时就创建好,在使用时获取。
缺点:无法做到延迟创建对象,在类加载时进行创建会导致初始化时间变长。
public class SingletonInner {
private static class Holder {
private static SingletonInner singleton = new SingletonInner();
}
private SingletonInner(){}
public static SingletonInner getSingleton(){
return Holder.singleton;
}
二:饿汉模式
原理:创建好一个静态变量,每次要用时直接返回。
缺点:无法做到延迟创建对象,在类加载时进行创建会导致初始化时间变长。
public class SingletonHungry {
private static SingletonHungry instance = new SingletonHungry();
private SingletonHungry() {
}
public static SingletonHungry getInstance() {
return instance;
}
三:懒汉模式
原理:延迟创建,在第一次用时才创建,之后每次用到就返回创建好的。
缺点:由于synchronized的存在,多线程时效率很低。
public class SingletonLazy {
private static volatile SingletonLazy instance;
private SingletonLazy() {
}
public static synchronized SingletonLazy getInstance() {
if (instance == null) {
instance = new SingletonLazy();
}
return instance;
}
四:双重校验锁懒汉模式
原理:在getSingleton()方法中,进行两次null检查。这样可以极大提升并发度,进而提升性能。
public class Singleton {
private static volatile Singleton singleton = null;//使用valatile,使该变量能被所有线程可见
private Singleton(){}
public static Singleton getSingleton(){
if(singleton == null){
synchronized (Singleton.class){//初始化时,加锁创建
if(singleton == null){//为避免在加锁过程中被其他线程创建了,再作一次非空校验
singleton = new Singleton();
}
}
}
return singleton;
}
五:上述4种方式实现单例模式的缺点
1、反序列化对象时会破环单例
反序列化对象时不会调用getXX()方法,于是绕过了确保单例的逻辑,直接生成了一个新的对象,破环了单例。
解决办法是:重写类的反序列化方法,在反序列化方法中返回单例而不是创建一个新的对象。
public class Singleton implements java.io.Serializable {
public static Singleton INSTANCE = new Singleton();
protected Singleton() {
}
//反序列时直接返回当前INSTANCE
private Object readResolve() {
return INSTANCE;
}
}
2、在代码中通过反射机制,直接调用类的私有构造函数创建新的对象,会破环单例
解决办法是:维护一个volatile的标志变量在第一次创建实例时置为false;重写构造函数,根据标志变量决定是否允许创建。
private static volatile boolean flag = true;
private Singleton(){
if(flag){
flag = false; //第一次创建时,改变标志
}else{
throw new RuntimeException("The instance already exists !");
}
六:枚举模式实现单例——将单例维护在枚举类中作为唯一实例
原理:定义枚举类型,里面只维护一个实例,以此保证单例。每次取用时都从枚举中取,而不会取到其他实例。
public enum SingletonEnum {
INSTANCE;
private String name;
public String getName(){
return name;
}
public void setName(String name){
this.name = name;
}
优点:
1)使用SingletonEnum.INSTANCE进行访问,无需再定义getInstance方法和调用该方法。
2)JVM对枚举实例的唯一性,避免了上面提到的反序列化和反射机制破环单例的情况出现:每一个枚举类型和定义的枚举变量在JVM中都是唯一的。
原因:枚举类型在序列化时仅仅是将枚举对象的name属性输出到结果中,反序列化的时候则是通过java.lang.Enum的valueOf方法来根据名字查找枚举对象。
同时,编译器禁止重写枚举类型的writeObject、readObject、readObjectNoData、writeReplace和readResolve等方法。
Java单例模式的几种实现的更多相关文章
- Java 单例模式的七种写法
Java 单例模式的七种写法 第一种(懒汉,线程不安全) public class Singleton { private static Singleton instance; private Sin ...
- 单例模式:Java单例模式的几种写法及它们的优缺点
总结下Java单例模式的几种写法: 1. 饿汉式 public class Singleton { private static Singleton instance = new Singleton( ...
- java单例模式的几种写法比较
概念: Java中单例模式是一种常见的设计模式,单例模式的写法有好几种,这里主要介绍三种:懒汉式单例.饿汉式单例.登记式单例. 单例模式有以下特点: 1.单例类只能有一个实例. 2.单例类必须自己创建 ...
- Java单例模式的6种写法
在Java中,单例有很多种写法,面试时,手写代码环节,除了写算法题,有时候也会让手写单例模式,这里记录一下单例的几种写法和优缺点. 初级写法 懒汉式 饿汉式 双锁检验 内部类 枚举式 1.初级写法 p ...
- java单例模式(两种常用模式)
单例模式是java中常见的设计模式 特点: 单例类只能有一个实例 单例类必须自己创建自己的唯一实例 单例类必须给所有的其他对象提供这一实例 单例模式是某个类只能有一个实例而且自动实例化并且向整个系统提 ...
- java 单例模式的几种写法
一.懒汉式 public class Singleton{ private static Singleton instance = null; private Singleton(){} public ...
- JAVA单例模式的几种写法
/** * 单例模式懒汉式(双重检锁线程安全.JDK1.5之后) */ public class Singleton { private static volatile Singleton singl ...
- Java单例模式的5种实现方式
1.饿汉式.不支持并发: package com.ou; //饿汉式 public class Singleton1 { private Singleton1() { } private static ...
- 用java单例模式实现面板切换
1.首先介绍一下什么是单例模式: java单例模式是一种常见的设计模式,那么我们先看看懒汉模式: public class Singleton_ { //设为私有方法,防止被外部类引用或实例 priv ...
随机推荐
- ESA2GJK1DH1K升级篇: 快速的移植升级程序到自己的项目(APP用户程序制作)
前言 用户程序比较简单,但是起着至关重要的作用 用户程序是和BootLoader程序相互配合的 拷贝文件到自己的项目 APP用户程序的 stmflash.c stmflash.h 和 上一节的Boot ...
- 洛谷p3385【模板】负环
最近很久没怎么写最短路的题导致这个题交了好多遍 AC率是怎么下来的自己心里没点数 SPFA虽然臭名昭著但是他可以用来判负环 如果一个点进队的次数大于等于n说明存在负环 这道题一开始memset我给di ...
- H5 + 3D + AR/VR 综述
近年来,H5,3D,AR,VR逐步进入人们的视野,H5生动活泼,3D注重视觉效果,AR打造虚实结合,VR则更加注重虚拟现实的产生. 第一部分,案例展示: H5+VR案例: 故事<不要惊慌,没有辐 ...
- Linux性能优化实战学习笔记:第四十九讲
一.上节回顾 上一期,我们一起梳理了,网络时不时丢包的分析定位和优化方法.先简单回顾一下.网络丢包,通常会带来严重的性能下降,特别是对 TCP 来说,丢包通常意味着网络拥塞和重传,进而会导致网络延迟增 ...
- [LeetCode] 46. Permutations 全排列
Given a collection of distinct integers, return all possible permutations. Example: Input: [1,2,3] O ...
- [LeetCode] 31. Next Permutation 下一个排列
Implement next permutation, which rearranges numbers into the lexicographically next greater permuta ...
- Postman测试后台使用@RequestBody接收参数的坑
问题原因:我在使用PostMan测试接口时发现数据传递不过来,是因为请求体定义为JSON数据,自动就传递不过来,虽然问题简单,但由于之前这个用的较少,所以就忽略了这点. 解决问题链接:https:// ...
- 五年微软DevOps MVP (也称TFS MVP)
笔者有幸第五次被微软授予MVP称号,高兴之余,在这里简单的介绍一下MVP的基本情况: 谁是 MVP? Microsoft 最有价值专家 (MVP) 是热情地与社区分享知识的技术专家.他们总是处于&qu ...
- Linux基础及入门介绍
一.linux发展历程 ①1969年unix诞生贝尔实验室 ②谭宁邦:minix unix ③斯托曼(stallman),公司:自由软件基金会(FSF) 项目:GNU 规则:GPL(所有人可以自由传播 ...
- Git系列四之在本地服务器搭建gitlab仓库管理(centeros环境下)
1.Git仓库管理 现在本地已经创建了git仓库,又在gitlab上创建了一个git仓库,并且让这两个仓库进行远程同步,这样gitlab仓库既可以备份也可以与他人协作管理远程仓库以及根据需要推送或拉取 ...