单例模式及其应用

news/2025/1/12 12:21:24/

单例模式介绍:

单例模式是一种常见的设计模式,其目的是确保某个类只有一个实例存在,并提供一个全局访问点。

在实现单例模式时,一般需要注意以下几点:

  1. 私有化构造函数:防止外部直接实例化对象。
  2. 私有静态成员变量:用于保存唯一的实例。
  3. 公有静态方法:提供获取该实例的唯一访问点。
public class Singleton
{// 使用 readonly 关键字确保只能在类构造函数或声明时赋值private static readonly Singleton instance = new Singleton();// 私有构造函数,防止外部直接实例化private Singleton() {}// 公有静态属性,提供访问单例实例的唯一访问点public static Singleton Instance{get{return instance;}}
}

在这个示例中:

  1. Singleton 类的构造函数是私有的,这样就无法从外部直接实例化该类。
  2. instance 字段是 Singleton 类的静态成员,并且使用 readonly 关键字,确保只能在声明时或类的构造函数中赋值,这保证了在应用程序生命周期内只会创建一个实例。
  3. Instance 属性是该类的公有静态属性,用于返回 Singleton 类的唯一实例。由于 instance 字段是静态的,所以可以在该属性的 get 访问器中直接返回它。

这种实现方式是线程安全的,因为在 C# 中,静态字段在类加载时就会被初始化,保证了在多线程环境下只有一个实例被创建。

使用场景:

当需要确保系统中某个类只有一个实例存在,并且该实例需要在全局范围内被访问时,可以考虑使用单例模式。以下是一些具体的使用场景:

  1. 数据库连接池:在一个应用程序中,通常会频繁地与数据库交互,为了提高性能和资源利用率,可以使用单例模式来实现数据库连接池。这样可以确保只有一个数据库连接池实例被创建,所有的数据库连接请求都可以共享该实例,避免了频繁创建和销毁数据库连接的开销。

  2. 配置管理器:在应用程序中,可能会有许多需要共享的配置信息,例如数据库连接信息、日志记录级别等。使用单例模式可以确保只有一个配置管理器实例存在,所有的模块都可以通过该实例访问和修改配置信息,保证了配置信息的一致性和统一管理。

  3. 日志记录器:在应用程序中,需要记录各种事件、错误和调试信息以便于调试和跟踪。使用单例模式可以确保只有一个日志记录器实例存在,所有的模块都可以通过该实例将日志信息写入到同一个日志文件中,避免了多个日志实例导致的日志信息分散和不一致的问题。

  4. 线程池:在应用程序中,可能会有大量的任务需要并发执行,为了提高性能和资源利用率,可以使用单例模式来实现线程池。这样可以确保只有一个线程池实例被创建,所有的任务都可以提交到该实例中进行并发执行,避免了频繁创建和销毁线程的开销。

  5. 缓存管理器:在应用程序中,可能会有大量的数据需要缓存,为了提高性能和资源利用率,可以使用单例模式来实现缓存管理器。这样可以确保只有一个缓存管理器实例被创建,所有的数据都可以通过该实例进行缓存和访问,避免了多个缓存实例导致的数据冗余和一致性问题。

以下是一个简单的 C# 示例,演示了如何使用单例模式实现线程池:

在许多应用程序中,需要频繁地执行一些异步任务,例如处理网络请求、计算密集型任务等。为了有效地管理线程资源,可以使用线程池来重复利用线程,避免频繁创建和销毁线程所带来的开销。

using System;
using System.Collections.Generic;
using System.Threading;public class ThreadPoolManager
{private static ThreadPoolManager instance;private static readonly object lockObject = new object();private Queue<Action> tasks = new Queue<Action>();private bool isRunning = false;private ThreadPoolManager() { }public static ThreadPoolManager Instance{get{if (instance == null){lock (lockObject){if (instance == null){instance = new ThreadPoolManager();}}}return instance;}}public void AddTask(Action task){lock (tasks){tasks.Enqueue(task);if (!isRunning){isRunning = true;ThreadPool.QueueUserWorkItem(ProcessTasks);}}}private void ProcessTasks(object state){while (true){Action task = null;lock (tasks){if (tasks.Count > 0){task = tasks.Dequeue();}else{isRunning = false;break;}}task?.Invoke();}}
}

在这个示例中,ThreadPoolManager 类是一个单例类,通过 Instance 属性获取其唯一实例。该类包含一个任务队列 tasks,用于存储待执行的任务。

AddTask 方法用于向线程池中添加任务。当添加任务时,如果线程池当前没有在运行,则启动一个新的线程来处理任务队列中的任务。

ProcessTasks 方法是一个循环,用于从任务队列中取出任务并执行。当任务队列为空时,将 isRunning 标志设置为 false,退出循环。

现在,让我们来看看如何使用这个线程池:

class Program
{static void Main(string[] args){ThreadPoolManager threadPool = ThreadPoolManager.Instance;for (int i = 0; i < 10; i++){int taskNumber = i;threadPool.AddTask(() =>{Console.WriteLine($"Task {taskNumber} is executing on thread {Thread.CurrentThread.ManagedThreadId}");Thread.Sleep(1000); // 模拟任务执行时间});}}
}

在这个例子中,我们首先获取了 ThreadPoolManager 的唯一实例 threadPool,然后向线程池中添加了 10 个任务。每个任务都会打印一条消息,并模拟执行一段时间。由于线程池是单例的,因此所有的任务都会被提交到同一个线程池中进行处理。

这个示例展示了如何使用单例模式实现一个简单的线程池,用于管理异步任务的执行。

 

 


http://www.ppmy.cn/news/1443432.html

相关文章

vue 实现 el-table 点击图标复制文本或者双击文本复制

方法一 双击复制&#xff1a; el-table 添加 cell-dblclick"dbClickCopyText" 双击 <el-table v-loading"loading" cell-dblclick"dbClickCopyText" :data"xxxList"></el-table> // 双击复制dbClickCopyText(row, col…

1.pytorch加载收数据(B站小土堆)

数据的加载主要有两个函数&#xff1a; 1.dataset整体收集数据&#xff1a;提供一种方法去获取数据及其label&#xff0c;告诉我们一共有多少数据&#xff08;就是自开始把要的数据和标签都收进来&#xff09; 2.dataloader&#xff0c;后面传入模型时候&#xff0c;每次录入数…

linux 上 jps 列出一堆 jar,如何快速定位 jar 文件启动位置?

例如&#xff0c;在 /data下有一个 xxx.jar &#xff0c;如果是通过 "java -jar /data/xxx.jar" 方式启动&#xff0c;则 jps会列出的名字中带 xxx.jar&#xff0c;这时再 "ps -ef | grep xxx.jar" 就会列出 更详细的信息&#xff0c;例如 "java -ja…

Android 振动和触感反馈功能失效问题分析

文章目录 一、 可以先通过adb来确定是否有打印Log&#xff0c;查看中相关的按键振动事件是否有效二、 适配按键事件三、延长振动时长 在Android13的项目(MTK平台)中遇到这样一个问题&#xff0c;在设置 - 提示音和振动 - 振动和触感反馈 - 打开按触反馈&#xff0c;但是按键没有…

机器人项目相关

机器人项目相关 1. Nvidia 1.1 Jetson 1.1.1 初步安装Riva教程 llamaspeakJetson AGX Orin踩坑记录&#xff08;1&#xff09;安装Riva 参考知乎链接&#xff1a;https://zhuanlan.zhihu.com/p/670007305 1.1.2 NVIDIA Jetson AI Lab 借助 NVIDIA Jetson™ 将生成式 AI…

先进制造aps专题三 为什么java语言不适合作为aps算法的开发语言

为什么java语言不适合作为aps算法的开发语言 主要两个原因 1 java的list在特定位置插入&#xff0c;其实是重新生成一个新list,而不像c就是指针操作 2 数据量大&#xff0c;运行时间长&#xff0c;会跑崩 所以商业aps产品&#xff0c;都是清一色的用c写aps算法 先进制造…

《AI音频类工具之二——​ 讯飞智作》

一.简介 官网:讯飞智作-提供文字转语音-语音合成-国内专业的一站式配音服务平台 讯飞智作是科大讯飞推出的一款基于人工智能技术的智能写作与配音工具,旨在利用自然语言处理、机器学习、深度学习等技术,帮助用户高效生成高质量的文本和音视频内容。 在文本写作方面,讯飞…

【Nginx】(五) Nginx作为微服务API网关的配置与应用

在微服务架构中&#xff0c;API网关是一个至关重要的组件&#xff0c;它不仅负责路由请求到正确的服务&#xff0c;还提供负载均衡、认证授权、限流、监控和日志记录等功能。在本博客中&#xff0c;我们将探讨一个在线教育平台如何使用Nginx作为API网关来解决流量管理和安全问题…