c#实现用SQL池,多线程定时批量执行SQL语句的方法
发布时间:2023-12-25 01:03:55
在实际项目开发中,业务逻辑层的处理速度往往很快,特别是在开发Socket通信服务的时候,网络传输很快,但是一旦加上数据库操作,性能一落千丈,数据库操作的效率往往成为一个系统整体性能的瓶颈。面对这问题,我们怎么办呢?好,下面我就为大家介绍一种方法:构建SQL池,分离业务逻辑层和数据访问层,让业务逻辑层从低效的数据库操作解脱,以提高系统整体性能。
(一)SQL池
SQL池是SQL容器,用于存放业务逻辑层抛过来的SQL语句。SQL池主要提供以下几种方法:
1)internal string Pop(),从池中取出SQL。
2)internal void Push(string item),增加一个SQL到池中。
3)internal string[] Clear(),清空SQL池,清空前,返回SQL池中所有SQL语句。
特别提醒一下,SQL池是面向多线程的,所以必须对公共资源SQL采取锁机制。这里采用互斥锁,当业务逻辑层线程往SQL池中抛入SQL语句时,禁止SQL执行线程执行SQL语句,反之,当SQL执行线程执行SQL语句时,也不允许业务逻辑层线程往SQL池中抛入SQL语句。为什么要这么做?因为SQL执行线程是批量执行SQL语句,在批量执行SQL语句前,会从池中取出所有SQL语句,如果此时业务逻辑层线程往SQL池中抛入SQL语句,则会导致这些SQL语句丢失,得不到执行。
下面是SQL池代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace Test1
{
sealed class SQLPool
{
//互斥锁
public static Mutex mutexSQLPool = new Mutex();
//SQL池
Stack<string> pool;
/// <summary>
/// 初始化SQL池
/// </summary>
internal SQLPool()
{
this.pool = new Stack<string>();
}
/// <summary>
/// 获取SQL池数量
/// </summary>
internal Int32 Count
{
get { return this.pool.Count; }
}
/// <summary>
/// 从池中取出SQL
/// </summary>
/// <returns></returns>
internal string Pop()
{
lock (this.pool)
{
return this.pool.Pop();
}
}
/// <summary>
/// 增加一个SQL到池中
/// </summary>
/// <param name="item"></param>
internal void Push(string item)
{
if (item.Trim() == "")
{
throw new ArgumentNullException("Items added to a SQLPool cannot be null");
}
//此处向SQL池中push SQL必须与Clear互斥
mutexSQLPool.WaitOne();
try
{
this.pool.Push(item); //此处如果出错,则不会执行ReleaseMutex,将会死锁
}
catch
{
}
mutexSQLPool.ReleaseMutex();
}
/// <summary>
/// 清空SQL池
/// 清空前,返回SQL池中所有SQL语句,
/// </summary>
internal string[] Clear()
{
string[] array = new string[] { };
//此处必须与Push互斥
mutexSQLPool.WaitOne();
try
{
array = this.pool.ToArray(); //此处如果出错,则不会执行ReleaseMutex,将会死锁
this.pool.Clear();
}
catch
{
}
mutexSQLPool.ReleaseMutex();
return array;
}
}
}
(二)SQL池管理
SQL池管理主要用于管理SQL池,向业务逻辑层线程和SQL执行线程提供接口。
业务逻辑层线程调用 public void PushSQL(string strSQL) 方法,用于向SQL池抛入SQL语句。
SQL执行线程调用 public void ExecuteSQL(object obj) 方法,用于批量执行SQL池中的SQL语句。
注意,SQL池管理类采用单例模型,为什么要采用单例模型?因为SQL池只能存在一个实例,无论是业务逻辑层线程还是SQL执行线程,仅会操作这一个实例,否则,将会导致SQL池不唯一,SQL执行无效。
下面是SQL池管理类代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
namespace Test1
{
class SQLPoolManage
{
//单例模型
public static readonly SQLPoolManage sqlPoolManage = new SQLPoolManage();
#region 属性
SQLPool poolOfSQL;
#endregion
#region 构造函数
/// <summary>
/// 初始化
/// </summary>
public SQLPoolManage()
{
this.poolOfSQL = new SQLPool();
}
#endregion
#region 方法
/// <summary>
/// 将SQL语句加入SQL池中
/// </summary>
/// <param name="strSQL"></param>
public void PushSQL(string strSQL)
{
this.poolOfSQL.Push(strSQL);
}
/// <summary>
/// 每隔一段时间,触发ExecuteSQL
/// ExecuteSQL用于执行SQL池中的SQL语句
/// </summary>
/// <param name="obj"></param>
public void ExecuteSQL(object obj)
{
if (this.poolOfSQL.Count > 0)
{
string[] array = this.poolOfSQL.Clear();
//遍历array,执行SQL
for (int i = 0; i < array.Length; i++)
{
if (array[i].ToString().Trim() != "")
{
try
{
//数据库操作
//......
}
catch
{
}
}
}
}
}
#endregion
}
}
(三)定时触发SQL执行线程
总结有以下三种方法:
方法一:调用线程执行方法,在方法中实现死循环,每个循环Sleep设定时间;
方法二:使用System.Timers.Timer类;
方法三:使用System.Threading.Timer;
代码如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
namespace Test1
{
class Program
{
static void Main(string[] args)
{
//向SQL池中抛入SQL语句
SQLPoolManage.sqlPoolManage.PushSQL("delete from tbl_test where id = 1");
//定时触发SQL执行线程
System.Threading.Timer threadTimer = new System.Threading.Timer(new System.Threading.TimerCallback(SQLPoolManage.sqlPoolManage.ExecuteSQL), null, 0, 100);
Console.ReadLine();
}
}
}


猜你喜欢
- SSO :同一个帐号在同一个公司不同系统上登陆 使用SpringSecurity实现类似于SSO登陆系统是十分简单的 下面我就搭
- 本文实例讲述了C#实现基于IE内核的简单浏览器。分享给大家供大家参考。具体如下:Form1.cs如下:using System;using
- String password = RandomUtil.generateString(10);源码如下:package com.javan
- 1概述众所周知,Java支持平台无关性、安全性和网络移动性。而Java平台由Java虚拟机和Java核心类所构成,它为纯Java程序提供了统
- 一般来说应用中比较常见的是折线图,直方图这种比较多,今天来写一个项目中的需求曲线图,也是在之前的折线图基础上改进而来,看效果图主要考虑曲线的
- 1.应用实例需求: 演示 Spring-Boot 通过表单注册用户,并支持上传图片2.代码实现代码实现-文件上传创建 templates/u
- maven周期maven的生命周期不止package,compile,clean。其实这是主要部分。以下截图其实展示的是maven的所有周期
- 教程展示了如何在Spring应用程序中使用GenericApplicationContext 。在该示例中,我们创建了一个Spring Bo
- 背景客户使用我们系统的时候,查询不带任何查询条件,查询就返回全部数据,500多万条数据啊,然后直接导出,数据量庞大,接口超时,这可苦了我们这
- 本文分析了Android编程中出现The connection to adb is down问题的解决方法。分享给大家供大家参考,具体如下:
- 1.前提:已安装JDK14,可以到jdk官网下载,或加QQ群835259695,快速免费下载2.不说没用的直接上jdk14环境下的jpack
- 本文实例讲述了Android编程实现ListView滚动提示等待框功能。分享给大家供大家参考,具体如下:其实原理很简单,只需要设置监听lis
- 1.依赖的jar文件 jsch-0.1.53.jar2.登录方式有密码登录,和密匙登录 代码:主函数:import java.ut
- 前几天的一个晚上突然想到微信红包应该有一个随机算法,就自己试着写了下,也不知道对不对,看了看网上的说法,好像到现在为止官方也没有给出一个确切
- 最近一个项目是一个基于winform的报告系统,根据一系列的查询参数计算出结果,最终生成一个格式规范的word文档,刚开始数据量不大(500
- summarydetail传统的Spring项目会有很多的配置文件,比如我们要使用Redis,一般除了对应的依赖的jar包我们还需要在app
- 本文以实例形式讲述了Android Touch事件分发过程,对于深入理解与掌握Android程序设计有很大的帮助作用。具体分析如下:首先,从
- 一、实验目的1. 掌握面向对象的编程思想、类与对象;2. 掌握类的封装性、继承性和多态性的作用;3. 掌握成员变量和成员方法的特性、构造方法
- 前言之前几篇我们介绍了贝塞尔曲线的原理、绘制曲线和动效实现,这些都是代码预设好的,如果我们要根据需要自行绘制曲线,就需要使用交互来实现了。本
- 本文实例为大家分享了Java手写线程池的实现代码,供大家参考,具体内容如下1.线程池是一种多线程处理形式,处理过程中将任务添加到队列,然后在