单例模式及其应用

ops/2024/9/18 12:47:15/ 标签: 单例模式, java, jvm

单例模式介绍:

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

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

  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/ops/29019.html

相关文章

截取视频第一帧当做封面

看了好多处理视频的框架 比如ffmpeg&#xff0c;很多都需要依赖安装第三方插件&#xff0c;比较麻烦&#xff0c;找到一个内嵌进去不需要额外安装的&#xff1a;jcodec 一 首先代码中添加依赖 <!--视频生成预览图用--><dependency><groupId>org.jcodec</…

Linux搭建mysql环境

搭建 MySQL 环境 1、使用 wget 下载安装包&#xff0c;下载到 opt 目录中 wget http://dev.mysql.com/get/mysql57-community-release-el7-10.noarch.rpm2、安装 MySQL 公钥 rpm -i mysql57-community-release-el7-10.noarch.rpmrpm --import https://repo.mysql.com/RPM-GP…

【Linux】理解 Ubuntu 中的 kill 和 killall 命令

我把我唱给你听 把你纯真无邪的笑容给我吧 我们应该有快乐的 幸福的晴朗的时光 我把我唱给你听 用我炙热的感情感动你好吗 岁月是值得怀念的留恋的 害羞的红色脸庞 谁能够代替你呀 趁年轻尽情的爱吧 最最亲爱的人啊 路途遥远我们在一起吧 &#x1f3b5; 叶…

AI智能体的未来:引领科技创新潮流

Agent AI智能体的未来 随着Agent AI智能体的智能化水平不断提高&#xff0c;它们在未来社会中的角色、发展路径以及可能带来的挑战也引起了广泛关注。快来分享一下你的看法吧~ 技术进步与创新 随着科技的发展&#xff0c;新的产业和商业模式不断涌现&#xff0c;创造了新的收…

CSS之动画

前言&#xff1a; 一个好的事物应该是有生命&#xff0c;而不是死板的&#xff0c;我们在制作网页时也是如此&#xff0c;为了让画面变得更加生动有趣&#xff0c;我们会给它加上动画的效果&#xff0c;例如过度、变形、旋转、放缩。 动画&#xff1a; 什么是动画&#xff1a;…

R语言 数据框的长、宽格式转换

Converting data between wide and long format 在宽、长格式之间转换数据 R语言中的大多数函数希望数据是长格式 但是&#xff0c;像 SPSS 通常使用宽格式数据 当你想把将数据从宽转换为长格式 常用的有两种方法&#xff1a; 1、gather() 和 spread() 来自 tidyr 包。 2、me…

【已解决】json文件太大无法打开怎么办+ijson报错

下载了一个json文档&#xff0c;尝试了全部的编辑器都打不开。。。 搜了搜或许可以使用ijson GitHub - ICRAR/ijson: Iterative JSON parser with Pythonic interfaces "Ijson is an iterative JSON parser with standard Python iterator interfaces." 示例代码&…

开发Chrome插件入门

开发Chrome插件&#xff08;也称为Chrome扩展&#xff09;是一个相对直接的过程&#xff0c;尤其对于已经熟悉HTML、CSS、JavaScript的前端开发者而言。以下是开发Chrome插件的基本步骤和示例&#xff1a; 1. 准备工作 首先&#xff0c;确保你有一个适合开发的环境。通常这意…

数据结构之顺序表的基本操作

搭配食用更佳哦~~ 数据结构之顺顺顺——顺序表-CSDN博客 1.定义一个动态顺序表 创建一个头文件 SeqList.h&#xff0c;进行准备工作 #pragma once #define _CRT_SECURE_NO_WARNINGS 1 #include<stdio.h> #include<stdlib.h> #include<assert.h> #include&q…

【人工智能基础】聚类实验分析

实验环境&#xff1a;anaconda、jupyter notebook、spyder 实现用到的类库&#xff1a;numpy、matplotlib、scikit-learn k均值聚类&#xff08;K-MEANS&#xff09; k均值聚类的原理&#xff1a; 选定k个聚类中心把数据集中距离聚类中心i最近的点都归属到一个簇根据每个簇中…

git如何回滚到指定版本【git操作】

要通过Git回滚到某个指定版本&#xff0c;可以按照以下步骤操作&#xff1a; 查看提交历史&#xff1a;使用 git log 命令查看提交历史&#xff0c;找到你想要回滚到的目标版本的提交哈希值。 回滚到指定版本&#xff1a;有几种不同的方法可以回滚到指定版本&#xff0c;以下是…

普冉PY32系列(十五) PY32F0系列的低功耗模式

目录 普冉PY32系列(一) PY32F0系列32位Cortex M0 MCU简介普冉PY32系列(二) Ubuntu GCC Toolchain和VSCode开发环境普冉PY32系列(三) PY32F002A资源实测 - 这个型号不简单普冉PY32系列(四) PY32F002A/003/030的时钟设置普冉PY32系列(五) 使用JLink RTT代替串口输出日志普冉PY32…

机器人系统ros2-开发实践04-ROS 2 启动文件管理大型项目的最佳实践

机器人上的大型应用通常涉及多个互连的节点&#xff0c;每个节点可以有许多参数。海龟模拟器中模拟多只海龟就是一个很好的例子。海龟模拟由多个海龟节点、世界配置以及 TF 广播器和监听器节点组成。在所有节点之间&#xff0c;存在大量影响这些节点的行为和外观的 ROS 参数。 …

C语言函数内存函数、memmove函数、、memcmp函数、memset函数等以及杨辉三角的介绍

文章目录 前言一、memmove函数----重叠内存拷贝二、memcmp----内存比较三、memset函数----内存设置四、杨辉三角总结 前言 C语言函数内存函数、memmove函数、、memcmp函数、memset函数等以及杨辉三角的介绍 一、memmove函数----重叠内存拷贝 库函数 #include <stdio.h&g…

大数据机器学习:常见模型评估指标

大数据机器学习&#xff1a;常见模型评估指标 一.模型评估综述 1.1 什么是模型评估 模型评估是指在机器学习中&#xff0c;对于一个具体方法输出的最终模型&#xff0c;使用一些指标和方法来评估它的泛化能力。这一步通常在模型训练和模型选择之后&#xff0c;正式部署模型之…

解决 DVWA 靶场 文件包含 The PHP function allow_url_include is not enabled.

报错如下&#xff1a; 在设置里面可以看到 allow_url_include 没有开启 这里需要修改配置文件&#xff1a;php.ini 但是注意&#xff0c;并不是 dvwa 靶场里的 php.ini 而是你 php 环境的 php.ini 使用记事本打开&#xff0c;检索&#xff1a;allow_url_include 修改为 On 后保…

BTC协议的设计【区块链学习笔记3】

BTC的协议&#xff0c;就是BTC应该怎么去设计&#xff0c;需要讨论的去中心化的货币要解决的问题&#xff1a; 1、货币的发行。&#xff08;谁有权力决定发行数字货币、货币什么时候发行、该发行多少&#xff09; --->只是单纯的签名会存在双花问题 2、验证交易的有效性。&a…

文本拷贝插件——clipboard.js

文本拷贝插件——clipboard.js clipboard.js是一款强大且实用的文本拷贝插件, 目前github的stars量30K以上 中文文档: http://www.clipboardjs.cn/ 1、通过npm工具安装 npm install clipboard --save 2、html文件直接导入 github搜索clipboard直接下载源码文件包 <sc…

web3j 合约方法调用源码分析

文章目录 调用方法流程FunctionRawTransactionCredentialssignMessagegenerateTransactionHashtoHexStringRawTransactionManager合约执行流程 FastRawTransactionManagerNoOpProcessor代码 调用方法流程 方法包括方法名&#xff0c;参数 返回值 &#xff08;Function&#xf…

Java 高级面试问题及答案(一)

Java 高级面试问题及答案 1. 解释Java中的多线程和并发&#xff0c;并给出一个你使用多线程的场景。 答案&#xff1a; 多线程是指在程序中同时运行多个线程&#xff0c;而并发是指在多线程环境下&#xff0c;多个线程在同一个时间点上执行不同的任务。Java中的多线程可以通过…