目录
[TOC]
什么是单例模式
单例设计模式(Singleton Pattern)是一种常用的软件设计模式,它保证一个类只有一个实例,并提供一个全局访问点。这种模式在需要确保某个类只有一个实例的情况下非常有用,常用于管理共享资源或限制对象的创建。
单例模式应用场景
- 配置管理:在应用程序中,可能需要使用一些全局的配置信息,例如数据库连接字符串、日志级别等。这些配置信息通常只需要一份,因此可以使用单例模式来实现。通过单例模式,我们可以在应用程序启动时创建一个唯一的实例,并在整个应用程序中共享这个实例。这样可以避免多个线程或进程同时访问和修改配置信息,从而保证了配置信息的一致性和可靠性。
- 日志记录:在应用程序中,可能需要使用一个全局的日志记录器,用于记录应用程序的运行情况和错误信息。同样地,只需要一份日志记录器即可,因此可以使用单例模式来实现。通过单例模式,我们可以在应用程序启动时创建一个唯一的实例,并在整个应用程序中共享这个实例。这样可以避免多个线程或进程同时访问和修改日志记录器,从而保证了日志记录的一致性和可靠性。
- 缓存管理:在应用程序中,可能需要使用一个全局的缓存系统,用于缓存一些数据以提高应用程序的性能。同样地,只需要一份缓存系统即可,因此可以使用单例模式来实现。通过单例模式,我们可以在应用程序启动时创建一个唯一的实例,并在整个应用程序中共享这个实例。这样可以避免多个线程或进程同时访问和修改缓存系统,从而保证了缓存系统的一致性和可靠性。
- 资源管理:在应用程序中,可能需要使用一些全局的资源,例如文件句柄、网络连接等。这些资源通常只需要一份,因此可以使用单例模式来实现。通过单例模式,我们可以在应用程序启动时创建一个唯一的实例,并在整个应用程序中共享这个实例。这样可以避免多个线程或进程同时访问和修改资源,从而保证了资源的一致性和可靠性。
代码
懒汉式单例模式(线程不安全)
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 
 | 
 
 public class LazySingleton {
 
 
 
 private static LazySingleton instance;
 
 
 
 
 private LazySingleton() {
 }
 
 
 public static LazySingleton getInstance() {
 
 if (instance == null) {
 instance = new LazySingleton();
 }
 return instance;
 }
 }
 
 | 
懒汉式单例模式(线程安全)
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 
 | 
 
 public class SafeLazySingleton {
 
 
 
 private static SafeLazySingleton instance;
 
 
 
 
 private SafeLazySingleton() {
 }
 
 
 
 
 public static synchronized SafeLazySingleton getInstance() {
 
 if (instance == null) {
 instance = new SafeLazySingleton();
 }
 return instance;
 }
 }
 
 | 
饿汉式单例模式
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 
 | 
 
 public class HungrySingleton {
 
 
 
 private static final HungrySingleton instance = new HungrySingleton();
 
 
 
 
 private HungrySingleton() {
 }
 
 
 
 
 public static HungrySingleton getInstance() {
 return instance;
 }
 }
 
 | 
双重检查锁单例模式
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 
 | 
 
 public class DoubleCheckSingleton {
 
 
 
 private static volatile DoubleCheckSingleton instance;
 
 
 
 
 private DoubleCheckSingleton() {
 }
 
 
 
 
 public static DoubleCheckSingleton getInstance() {
 if (instance == null) {
 synchronized (DoubleCheckSingleton.class) {
 if (instance == null) {
 
 instance = new DoubleCheckSingleton();
 }
 }
 }
 return instance;
 }
 }
 
 | 
静态内部类单例模式
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 
 | 
 
 public class StaticInnerClassSingleton {
 
 
 
 private StaticInnerClassSingleton() {
 }
 
 ;
 
 
 
 
 
 private static class Singleton {
 private static final StaticInnerClassSingleton INSTANCE = new StaticInnerClassSingleton();
 }
 
 
 
 
 public static StaticInnerClassSingleton getInstance() {
 return Singleton.INSTANCE;
 }
 
 }
 
 | 
枚举单例模式
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 
 | 
 
 public enum EnumSingleton {
 INSTANCE;
 int value;
 
 
 
 
 private EnumSingleton() {
 value = 1;
 System.out.println("INSTANCE now created!");
 }
 
 public int getValue() {
 return value;
 }
 
 public void setValue(int value) {
 this.value = value;
 }
 }
 
 | 
测试
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 
 | package com.xiaofei.singleton;
 import org.junit.Test;
 
 
 
 
 public class SingletonTest {
 
 @Test
 public void lazySingletonTest() {
 System.out.println("懒汉式单例模式(线程不安全)");
 LazySingleton instance = LazySingleton.getInstance();
 System.out.println(instance);
 System.out.println("懒汉式单例模式(线程不安全)\n");
 
 }
 
 @Test
 public void safeLazySingleton() {
 System.out.println("懒汉式单例模式(线程安全)");
 SafeLazySingleton instance = SafeLazySingleton.getInstance();
 System.out.println(instance);
 System.out.println("懒汉式单例模式(线程安全)\n");
 }
 
 @Test
 public void hungrySingleton() {
 System.out.println("饿汉式单例模式");
 HungrySingleton instance = HungrySingleton.getInstance();
 System.out.println(instance);
 System.out.println("饿汉式单例模式\n");
 }
 
 @Test
 public void doubleCheckSingleton() {
 System.out.println("双重检查锁单例模式");
 DoubleCheckSingleton instance = DoubleCheckSingleton.getInstance();
 System.out.println(instance);
 System.out.println("双重检查锁单例模式\n");
 }
 
 @Test
 public void staticInnerClassSingleton() {
 System.out.println("静态内部类单例模式");
 StaticInnerClassSingleton instance = StaticInnerClassSingleton.getInstance();
 System.out.println(instance);
 System.out.println("静态内部类单例模式\n");
 }
 
 @Test
 public void enumSingleton() {
 System.out.println("枚举单例模式");
 EnumSingleton singleton = EnumSingleton.INSTANCE;
 System.out.println(singleton.getValue());
 singleton.setValue(2);
 System.out.println(singleton.getValue());
 System.out.println("枚举单例模式\n");
 
 }
 }
 
 | 

总结
- 懒汉式单例模式(线程不安全): 
- 优点:实现简单,性能好。 
- 缺点:线程不安全,需要在多线程环境下进行同步处理。
 
- 懒汉式单例模式(线程安全): 
- 优点:线程安全,不需要额外的同步处理。
- 缺点:实现相对复杂,性能略差于饿汉式单例模式。
 
- 饿汉式单例模式: 
- 优点:线程安全,性能好。 
- 缺点:创建实例时会耗费一定的时间和资源。
 
- 双重检查锁单例模: 
- 静态内部类单例模式: 
- 枚举单例模式: 
- 优点:线程安全,性能好。 
- 缺点:枚举类型本身不能被修改,因此如果需要扩展功能则需要修改枚举类型。
 
综上所述,不同的单例模式适用于不同的场景。根据实际的需求选择合适的单例模式可以提高程序的效率,并保证单例实例的唯一性。