【c#】线程Monitor.Wait和Monitor.Pulse使用
介绍
以一个简易版的数据库连接池的实现来说明一下
连接池的connection以队列来管理
getConnection的时候,如果队列中connection个数小于50,且暂时无可用的connection(个数为0或者peek看下头部需要先出那个元素还处于不可用状态),就新建连接并建立连接,开始一直新建到50个connection,就是_currentPoolSize =50
如果队列中connection个数大于等于50,且暂时无可用的connection(个数为0或者peek看下头部需要先出那个元素还处于不可用状态),就等着Monitor.Wait(_connectionPoolQueueLock)
returnConnection的时候,使用Monitor.Pulse(_connectionPoolQueueLock) 随机通知一个wait的线程可以继续getConnection了
using System;
using System.Collections.Generic;
using System.Data;
using System.Threading;
using Mono.Data.Sqlite;namespace demo.unity.sqlite
{public class SQLiteConnectionManager{private Queue<Tuple<SqliteConnection, DateTime>> _connectionPoolQueue;private object _connectionPoolQueueLock = new object();private const int maxPoolSize = 50;private volatile bool _disposed;private int _currentPoolSize;private readonly System.Timers.Timer _cleanupTimer = new System.Timers.Timer(10 * 60 * 1000);public SQLiteConnectionManager(){_connectionPoolQueue = new Queue<Tuple<SqliteConnection, DateTime>>(maxPoolSize);_cleanupTimer.Elapsed += _cleanupTimerElapsed;_cleanupTimer.AutoReset = true;_cleanupTimer.Start();}private void _cleanupTimerElapsed(object sender, System.Timers.ElapsedEventArgs e){lock (_connectionPoolQueueLock){while (_connectionPoolQueue.Count > 0 && (DateTime.UtcNow - _connectionPoolQueue.Peek().Item2).TotalMinutes > 15){var tup = _connectionPoolQueue.Dequeue();tup.Item1.Dispose();_currentPoolSize--;}}}private SqliteConnection _createNewConnection(SqliteConnectionStringBuilder builder){var connection = new SqliteConnection(builder.ConnectionString);connection.Open();return connection;}public SqliteConnection getConnection(SqliteConnectionStringBuilder builder){lock (_connectionPoolQueueLock){// count == 0 or queue.peek no use connectionwhile (_connectionPoolQueue.Count == 0 || _connectionPoolQueue.Peek().Item1.State != ConnectionState.Open){if (_disposed){throw new ObjectDisposedException("The DB connection pool is is already disposed");}if (_currentPoolSize < maxPoolSize){// create and open connectionvar connection = _createNewConnection(builder);_connectionPoolQueue.Enqueue( new Tuple<SqliteConnection, DateTime>(connection, DateTime.UtcNow));_currentPoolSize++;}else{Monitor.Wait(_connectionPoolQueueLock);}}return _connectionPoolQueue.Dequeue().Item1;}}public void returnConnection(SqliteConnection connection){if (connection == null){return;}lock (_connectionPoolQueueLock){_connectionPoolQueue.Enqueue(new Tuple<SqliteConnection, DateTime>(connection, DateTime.UtcNow));Monitor.Pulse(_connectionPoolQueueLock);}}public void dispose(){lock (_connectionPoolQueueLock){_disposed = true;while (_connectionPoolQueue.Count > 0){var tup = _connectionPoolQueue.Dequeue();tup.Item1?.Dispose();_currentPoolSize--;}// wake up any waiting threadsMonitor.PulseAll(_connectionPoolQueueLock);}_cleanupTimer.Stop();_cleanupTimer.Dispose();}}
}相关文章:
【c#】线程Monitor.Wait和Monitor.Pulse使用
介绍 以一个简易版的数据库连接池的实现来说明一下 连接池的connection以队列来管理 getConnection的时候,如果队列中connection个数小于50,且暂时无可用的connection(个数为0或者peek看下头部需要先出那个元素还处于不可用状态)…...
GitLab平台安装中经典安装语句含义解析
yum -y install policycoreutils openssh-server openssh-clients postfix 这是一个Linux命令,用于使用YUM包管理器安装指定的软件包。下面是对这个命令各部分的解释: yum:这是一个Linux命令行工具,用于管理RPM(Red …...
湘潭大学 2023年下学期《C语言》作业0x03-循环1 XTU OJ 1094,1095,1096,1112,1113
第一题 #include<stdio.h>int main() {int t;int count1;scanf("%d",&t);while(t--){int a,b,c;scanf("%d%d",&a,&b);cab;printf("Case %d: %d\n",count,c);count;}return 0; } 记住多样例输入的模板,熟悉计数器…...
【Linux系统满足产品实时性需求】
一、背景: 应用实时性:应用程序1以固定周期执行实时算法; 应用程序2以固定周期,执行串口收发; 驱动实时性:驱动sdio接口,实现与FPGA数据交互,实现串口数据收发。 二、实时性保证&…...
不用休眠的 Kotlin 并发:深入对比 delay() 和 sleep()
本文翻译自: https://blog.shreyaspatil.dev/sleepless-concurrency-delay-vs-threadsleep 毫无疑问,Kotlin 语言中的协程 Coroutine 极大地帮助了开发者更加容易地处理异步编程。该特性中封装的诸多高效 API,可以确保开发者花费更小的精力去…...
在Ubuntu中批量创建用户
一、背景知识 在Linux操作系统中创建新用户可以使用useradd或adduser命令。 使用useradd命令创建用户时,不会在/home目录下创建用户文件夹,需要用户自己指定主目录和bash目录的位置。同时,创建的用户没有设置密码,无法进行登录&a…...
汽车冲压车间的RFID技术设计解决方案
一、RFID技术的基本原理 RFID技术是一种利用非接触式自动识别的技术,通过将RFID标签放置在被识别物品上,并使用RFID读写器对标签进行扫描和识别,实现对物品的自动识别和追踪。RFID标签分为被动式和主动式两种。被动式标签无内置电源…...
TCP 和UDP通信流程
TCP 通信流程 根据上图可以看到,TCP 服务器和客户端通信分为 TCP 服务端和客户端,需要先建立服务 端然后再建立客户端与之连接进行数据交互。 服务端编程步骤: 1.使用 socket 创建流式套接字 2.使用 bind 绑定将服务器绑定到 IP 3.listen…...
Swift SwiftUI CoreData 过滤数据 1
Xcode: Version 14.3.1 (14E300c) iOS: 16 预览: Code: import SwiftUI import CoreDatastruct TodosSearch: View {State private var search_title "测试"FetchRequest var todos_search: FetchedResults<Todo>init() {let request: NSFetchReq…...
【uniapp】subnvue组件数据更新视图未更新问题
背景 : 页面中的弹窗使用了subnvue来写, 根据数据依次展示一个一个的弹窗, 点击"关闭"按钮关闭当前弹窗, 显示下一个弹窗 问题 : 当点击关闭时( 使用的splice() ), 数据更新了 , 而视图没有更新, 实际上splice() 是不仅更新数据, 也可以更新视图的 解决 : this.$fo…...
Unity编辑器拓展-Odin
1.相比于原生Unity的优势 Unity不支持泛型类型序列化,例如字典原生Unity不支持序列化,而Odin可以继承序列化的Mono实现功能强大且使用简单,原生Unity想实现一些常见的功能需要额外自己编写Unity扩展的编码,实现功能只需要加一个特…...
小红书婴童产业探索,解析消费者需求!
在消费升级、市场引导的背景下,众多产业都在悄然发生着变化,其中“婴童产业”就是非常有代表性的一个。今天就来深入分析小红书婴童产业探索,解析消费者需求! 一、何为婴童产业 事实上,婴童产业,并不仅仅局…...
离线安装mysql客户端
下载路径 oracle网站总是在不断更新,所以下载位置随时可能变动但万变不离其宗,学习也要学会一通百通。 首先直接搜索,就能找找到mysql官网 打开网站,并点击 DOWNLOADS 往下滚动,找到社区版下载按钮。…...
Docker 数据管理
管理 Docker 容器中数据主要有两种方式: 数据卷(Data Volumes) 数据卷容器(DataVolumes Containers)。 数据卷 数据卷是一个供容器使用的特殊目录,位于容器中。可将宿主机的目录挂载到数据卷上…...
数据统计--图形报表--ApacheEcharts技术 --苍穹外卖day10
Apache Echarts 营业额统计 重点:已完成订单金额要排除其他状态的金额 根据时间选择区间 设计vo用于后端向前端传输数据,dto用于后端接收前端发送的数据 GetMapping("/turnoverStatistics")ApiOperation("营业额统计")public Result<TurnoverReportVO…...
【kubernetes的三种网络】
kubernetes的三种网络 一、三种网络service网络(service是虚拟IP地址)pod网络(pod的IP地址 docker容器的IP)节点网络(网络服务器上的物理网卡IP) 二、其他网络flannel一、vxlan(隧道方案)1.定义2.优势3.工作…...
Java中树形菜单的实现方式(超全详解!)
前言 这篇文中,我一共会用两种方式来实现目录树的数据结构,两种写法逻辑是一样的,只是一种适合新手理解,一种看着简单明了但是对于小白不是很好理解。在这里我会很详细的讲解每一步代码,主要是方便新人看懂࿰…...
基于Uniswap V3的去中心化前端现货交易平台Oku正式登陆Moonbeam
波卡上的Uniswap v3合约由Moonbeam智能合约、Oku前端,以及Wormhole远程路由技术共同实现。 跨链互连应用的最佳去中心化开发平台Moonbeam宣布Uniswap现已正式登陆。此次是Uniswap产品作为一个主流的DEX首次涉足Polkadot生态。用户可以通过新的、易于使用的Oku界面与…...
leetcode 每日一题复盘(10.9~10.15)
leetcode 101 对称二叉树 这道题一开始想是用层序遍历,看每一层是否都对称,遇到一个问题就是空指针(子树为空)无法记录下来,同时会导致操作空指针的问题,因此需要修改入队条件,并用一个标志去表示空指针 vector<int>numv;for(int i0;i<size;i){TreeNode*frontque.fro…...
【云计算网络安全】DDoS 缓解解析:DDoS 攻击缓解策略、选择最佳提供商和关键考虑因素
文章目录 一、前言二、什么是 DDoS 缓解三、DDoS 缓解阶段四、如何选择 DDoS 缓解提供商4.1 网络容量4.2 处理能力4.3 可扩展性4.4 灵活性4.5 可靠性4.6 其他考虑因素4.6.1 定价4.6.2 所专注的方向 文末送书《数据要素安全流通》本书编撰背景本书亮点本书主要内容 一、前言 云…...
关于nvm与node.js
1 安装nvm 安装过程中手动修改 nvm的安装路径, 以及修改 通过nvm安装node后正在使用的node的存放目录【这句话可能难以理解,但接着往下看你就了然了】 2 修改nvm中settings.txt文件配置 nvm安装成功后,通常在该文件中会出现以下配置&…...
LeetCode - 394. 字符串解码
题目 394. 字符串解码 - 力扣(LeetCode) 思路 使用两个栈:一个存储重复次数,一个存储字符串 遍历输入字符串: 数字处理:遇到数字时,累积计算重复次数左括号处理:保存当前状态&a…...
蓝牙 BLE 扫描面试题大全(2):进阶面试题与实战演练
前文覆盖了 BLE 扫描的基础概念与经典问题蓝牙 BLE 扫描面试题大全(1):从基础到实战的深度解析-CSDN博客,但实际面试中,企业更关注候选人对复杂场景的应对能力(如多设备并发扫描、低功耗与高发现率的平衡)和前沿技术的…...
测试markdown--肇兴
day1: 1、去程:7:04 --11:32高铁 高铁右转上售票大厅2楼,穿过候车厅下一楼,上大巴车 ¥10/人 **2、到达:**12点多到达寨子,买门票,美团/抖音:¥78人 3、中饭&a…...
cf2117E
原题链接:https://codeforces.com/contest/2117/problem/E 题目背景: 给定两个数组a,b,可以执行多次以下操作:选择 i (1 < i < n - 1),并设置 或,也可以在执行上述操作前执行一次删除任意 和 。求…...
什么是EULA和DPA
文章目录 EULA(End User License Agreement)DPA(Data Protection Agreement)一、定义与背景二、核心内容三、法律效力与责任四、实际应用与意义 EULA(End User License Agreement) 定义: EULA即…...
根据万维钢·精英日课6的内容,使用AI(2025)可以参考以下方法:
根据万维钢精英日课6的内容,使用AI(2025)可以参考以下方法: 四个洞见 模型已经比人聪明:以ChatGPT o3为代表的AI非常强大,能运用高级理论解释道理、引用最新学术论文,生成对顶尖科学家都有用的…...
安宝特方案丨船舶智造的“AR+AI+作业标准化管理解决方案”(装配)
船舶制造装配管理现状:装配工作依赖人工经验,装配工人凭借长期实践积累的操作技巧完成零部件组装。企业通常制定了装配作业指导书,但在实际执行中,工人对指导书的理解和遵循程度参差不齐。 船舶装配过程中的挑战与需求 挑战 (1…...
【VLNs篇】07:NavRL—在动态环境中学习安全飞行
项目内容论文标题NavRL: 在动态环境中学习安全飞行 (NavRL: Learning Safe Flight in Dynamic Environments)核心问题解决无人机在包含静态和动态障碍物的复杂环境中进行安全、高效自主导航的挑战,克服传统方法和现有强化学习方法的局限性。核心算法基于近端策略优化…...
Go 并发编程基础:通道(Channel)的使用
在 Go 中,Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式,用于在多个 Goroutine 之间传递数据,从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...
