单例模式的几种实现方式,直接上代码吧
package com.huang.sington;
/**
* 饥汉模式
* @author 黄
*
*/
public class ExampleHunger {
/**
* final修饰的对象会在类加载的准备阶段进行赋值,造成内存的浪费
*/
private final static ExampleHunger exampleFull = new ExampleHunger();
private ExampleHunger() {
}
/**
* 饱汉模式,会事先先类加载阶段将对象初始化到内存,因为对象不使用,会占用内存空间,造成资源浪费
* @return
*/
public static ExampleHunger getInstance() {
return exampleFull;
}
}
-----------------------------------------------------------------------------------------------------------------------------------------------
package com.huang.sington;
/**
* 单例 懒汉模式
* @author 黄
*
*/
public class ExampleLazy {
private static ExampleLazy exampleHunger = null;
private ExampleLazy() {
}
/**
* 加上synchronized关键字产生性能问题,不加会线程不安全
* @return
*/
public static synchronized ExampleLazy getInstance() {
if(exampleHunger == null) {
exampleHunger = new ExampleLazy();
}
return exampleHunger;
}
}
----------------------------------------------------------------------------------------------------------------------------------------------
package com.huang.sington;
/**
* 双重检查模式
* @author 黄
*
*/
public class ExampleDoubleCheck {
/**
* 需要加上volatile修饰,volatile保证内存可见性和禁止指令重排
* 这里为什么要加这个关键字呢
* exampleDoubleCheck = new ExampleDoubleCheck();
* 这个动作分三步
* 1、分配给实例内存空间
* 2、调用构造方法初始化成员变量
* 3、将exampleDoubleCheck指向分配的内存
* 这里的三步1步骤是固定的,但是2、3步可能顺序不同,
* 假如有一个线程初始化先执行第3步,在第二步还没有执行的情况下,另一个线程进来直接获取到exampleDoubleCheck对象
* 这里获取到的对象在后续使用中可能会发生错误,所以要加上volatile关键字
*/
private volatile static ExampleDoubleCheck exampleDoubleCheck = null;
private ExampleDoubleCheck() {
}
public static ExampleDoubleCheck getInstance() {
if(exampleDoubleCheck == null) {
//加上全局锁
synchronized (ExampleDoubleCheck.class) {
if(exampleDoubleCheck == null) {
exampleDoubleCheck = new ExampleDoubleCheck();
}
}
}
return exampleDoubleCheck;
}
}
----------------------------------------------------------------------------------------------------------------------------------------------
package com.huang.sington;
/**
* 采用静态内部类的方式获取
* @author 黄
*
*/
public class ExampleStaticInner {
static {
System.out.println("初始化类 ExampleStaticInner");
}
private ExampleStaticInner() {
}
/**
* 这里使用用静态内部的方式实现单例,只有在调用getInstance方法时才加载静态内部类
* 可以防止在饥汉模式中在类加载阶段就已经初始化的对象,造成内存的浪费
* @return
*/
public static ExampleStaticInner getInstance() {
System.out.println("第一次加载ExampleStaticInner getInstance 方法");
return ExampleSingtonHandler.exampleStaticInner;
}
public static void test() {
System.out.println("第一次加载ExampleStaticInner test 方法");
}
private static class ExampleSingtonHandler {
private static final ExampleStaticInner exampleStaticInner = new ExampleStaticInner();
static {
System.out.println("初始化静态内部类 ExampleSingtonHandler");
}
}
}
关于静态内部类的实现方式,谢了一个测试方法看其加载过程
package com.huang.sington;
import org.junit.Test;
public class ExampleTest {
/**
* 测试静态内部类实行单例的加载过程
*/
@Test
public void staticInnerTest() {
//停一秒
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("调用test初始化ExampleStaticInner静态代码块和打印test文字开始");
ExampleStaticInner.test();
System.out.println("调用getInstance方法打印getInstance中文字并开始加载静态内部类");
ExampleStaticInner.getInstance();
}
}
运行结果
调用test初始化ExampleStaticInner静态代码块和打印test文字开始
初始化类 ExampleStaticInner
第一次加载ExampleStaticInner test 方法
调用getInstance方法打印getInstance中文字并开始加载静态内部类
第一次加载ExampleStaticInner getInstance 方法
初始化静态内部类 ExampleSingtonHandler
相关推荐
### JAVA单例模式的几种实现方法 #### 一、饿汉式单例类 饿汉式单例类是在类初始化时就已经完成了实例化的操作。这种实现方式简单且线程安全,因为实例化过程是在编译期间完成的,不会受到多线程的影响。 **代码...
这个讲的是单例模式的多种不同实现方式,希望对单例感兴趣的同学看看
下面将详细介绍单例模式的几种常见实现方式。 1. 饿汉式(静态常量) 饿汉式单例在类加载时就完成了初始化,因此线程安全。这种方式简单且效率高,但如果单例对象不被使用,会造成内存浪费。 ```java public class...
以下是几种常见的单例模式实现方式: 1. **饿汉式(静态常量)**: 这是最简单的实现方式,它在类加载时就完成了初始化,因此是线程安全的。 ```java public class Singleton { private static final Singleton...
在多线程环境下,我们需要确保单例实例的创建只发生一次,以上几种方式除了懒汉式(线程不安全)外,都能保证线程安全。对于反序列化测试,由于默认反序列化会生成新实例,需要重写 `readResolve()` 方法来防止这种...
下面我们将深入探讨单例模式的几种实现方式。 ### 1. 饿汉式(静态常量) 饿汉式单例在类加载时就完成了初始化,因此是线程安全的。代码如下: ```java public class Singleton { private static final ...
单例模式的实现方式有很多种,下面我们将详细探讨几种常见的单例模式的实现方法: 1. 饿汉式(静态常量): 这种方式在类加载时就完成了初始化,因此是线程安全的。 ```java public class Singleton { private ...
在 Java 中,单例模式的写法有好几种,主要有懒汉式单例、饿汉式单例、登记式单例等。 懒汉式单例是一种常见的单例模式实现方式,它在第一次调用的时候实例化自己。下面是懒汉式单例的四种写法: 1、基本懒汉式...
以下是对这六种常见单例模式实现方式的详细解释: 1. **饿汉式(静态常量)** 这是最简单的单例实现,它在类加载时就创建了实例,线程安全。 ```java public class Singleton { private static final Singleton...
此外,单例模式还有几种变体,比如静态内部类单例和枚举单例。静态内部类单例利用Java类加载机制保证了线程安全,而枚举单例则是Java中实现单例的最佳方式,因为它天然支持序列化且防止反射攻击。 在代码实现上,...
根据给定的信息,本文将详细解释几种常见的单例模式,并通过具体的Java代码示例来阐述每种模式的特点和实现方式。 ### 单例模式简介 单例模式是一种常用的软件设计模式,它保证一个类只有一个实例,并提供一个全局...
单例模式的常见实现方式有以下几种: 1. **饿汉式(Eager Initialization)**:在类加载时就完成了初始化,所以类加载比较慢,但获取实例的速度快,线程安全。这是通过静态常量或者静态初始化块来实现的。 ```java...
"C++ 单例模式的几种实现方式研究" 单例模式是设计模式中最常应用的一种模式,也是面试官最喜欢的题目。但是,如果没有学过设计模式的人,可能不会想到要去应用单例模式,面对单例模式适用的情况。 单例模式的主要...
以上就是关于单例模式的一些核心概念和常见实现方式。在实际开发中,根据需求和场景选择合适的实现方式至关重要,以平衡性能和资源使用。同时,需要注意的是,过度依赖单例可能导致系统设计过于紧密,不利于测试和...
单例模式的应用非常广泛,特别是在以下几种场景中: - **资源管理**:比如数据库连接池、线程池等,这些资源非常宝贵,重复创建不仅浪费资源,还可能引发性能问题。 - **配置信息管理**:如系统配置类,通常只需要...
首先,实现C#单例模式通常有几种常见方法: 1. 饿汉式(静态常量): 这种方式在类加载时就完成了实例化,线程安全,但可能导致不必要的内存占用。 ```csharp public class Singleton { private static ...
单例模式的实现方式有很多种,主要分为以下几种: 1. **饿汉单例模式**:在类加载时就完成初始化,因此静态变量`instance`会随着类的加载而被创建。这种方式线程安全,且因为单例在类加载时已经创建,所以不存在多...
本篇文章将深入探讨Python中实现单例模式的几种方式以及它们的优缺点和优化策略。 首先,Python的模块机制实际上天然地支持单例模式。当模块首次被导入时,解释器会执行模块中的所有代码,生成相应的`.pyc`文件。...
实现单例模式有多种方式,下面详细介绍几种常见的实现方法: 1. **饿汉式(静态常量)**: 在类加载时就创建了单例对象,这种方式简单且线程安全,但由于类加载时就完成了初始化,所以即使没有使用,也会消耗内存...