用线程池解决多用户计算的问题

本文介绍了作者在项目实践中使用线程池技术的经验,探讨了如何通过动态调整线程池大小来提高服务器性能,并分享了一个具体实现案例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

   今天从公司辞职回来.从项目实践开发中得到不少经验..这里拿出来分享一下.公司做的是电力10KV以下配网..主要有工程量统计.生成报表.模块的拼接等需要计算的模块..这些模块会造成服务器性能下降.并且在线用户会达到200人..以自己的经验来看..搞个线程池..来做到同时计算的目的..  

简单线程池存在一些问题,比如如果有大量的客户要求服务器为其服务,但由于线程池的工作线程是有限的,服务器只能为部分客户服务,其它客户提交的任务,只能在任务队列中等待处理。一些系统设计人员可能会不满这种状况,因为他们对服务器程序的响应时间要求比较严格,所以在系统设计时可能会怀疑线程池技术的可行性,但是线程池有相应的解决方案。调整优化线程池尺寸是高级线程池要解决的一个问题。主要有下列解决方案:

方案一:

动态增加工作线程 在一些高级线程池中一般提供一个可以动态改变的工作线程数目的功能,以适应突发性的请求。一旦请求变少了将逐步减少线程池中工作线程的数目。当然线程增加可以采用一种超前方式,即批量增加一批工作线程,而不是来一个请求才建立创建一个线程。批量创建是更加有效的方式。该方案还有应该限制线程池中工作线程数目的上限和下限。否则这种灵活的方式也就变成一种错误的方式或者灾难,因为频繁的创建线程或者短时间内产生大量的线程将会背离使用线程池原始初衷--减少创建线程的次数。举例:Jini中的TaskManager,就是一个精巧线程池管理器,它是动态增加工作线程的。SQL Server采用单进程(Single Process)多线程(Multi-Thread)的系统结构,1024个数量的线程池,动态线程分配,理论上限32767。  

方案二:

优化工作线程数目 如果不想在线程池应用复杂的策略来保证工作线程数满足应用的要求,你就要根据统计学的原理来统计客户的请求数目,比如高峰时段平均一秒钟内有多少任务要求处理,并根据系统的承受能力及客户的忍受能力来平衡估计一个合理的线程池尺寸。线程池的尺寸确实很难确定,所以有时干脆用经验值。举例:在MTS中线程池的尺寸固定为100。  

方案三:

一个服务器提供多个线程池 在一些复杂的系统结构会采用这个方案。这样可以根据不同任务或者任务优先级来采用不同线程池处理。举例:COM+用到了多个线程池。这三种方案各有优缺点。在不同应用中可能采用不同的方案或者干脆组合这三种方案来解决实际问题。

我采用的是方案三.根据不同任务或者任务优先级来采用不同线程池处理


Imports **.**.Common
Imports **.**.SystemFramework

Imports System
Imports System.Threading
Imports System.Collections
#Region "线程池类"
'''<summary>
'''--------------------------------------------------
''' Copyright (C) 2000-2010 ******有限公司
'''  文件名:ClkTaskDA.vb
'''  编写者:fanliang11
'''    功能:线程池,包括添加任务、取消任务、是否包含任务、重置线程池、关闭线程池等功能 
'''编写日期:2008年05月15日
'''--------------------------------------------------
''' </summary>
Public Class ThreadPool
#Region "构造函数"
    ''' <summary>
    ''' 默认构造函数
    ''' 创建默认线程数的线程池
    ''' </summary>
    Shared Sub New()
        Initialize()
    End Sub
#End Region

 


#Region "公共方法"

    ''' <summary>
    ''' 是否包含指定名称的任务
    ''' </summary>
    ''' <param name="pTaskName">任务名称</param>
    ''' <returns>如果包含返回true,否则返回false</returns>
    Public Shared Function Contains(ByVal pTaskName As String) As Boolean
        Dim containsTask As Boolean = False
        SyncLock mPoolLock
            containsTask = mTaskNameList.Contains(pTaskName)
        End SyncLock
        Return containsTask
    End Function

    ''' <summary>
    ''' 获取等待执行的任务数
    ''' </summary>
    ''' <param name="pTaskType">任务类型</param>
    ''' <returns></returns>
    Public Shared Function GetWaitingTaskNum(ByVal pTaskType As BoWeiTaskType) As Integer
        Dim waitingTaskNum As Integer = 0
        SyncLock mPoolLock
            Select Case pTaskType
                Case BoWeiTaskType.STATPROJECT
                    waitingTaskNum = mStatProjectQueue.Count
                    Exit Select

                    Exit Select
                Case BoWeiTaskType.COMMON

                    waitingTaskNum = mCommonQueue.Count
                    Exit Select

            End Select
        End SyncLock
        Return waitingTaskNum
    End Function

    ''' <summary>
    ''' 添加任务至线程池
    ''' </summary>
    ''' <param name="pCallback">回调函数的委托</param>
    ''' <param name="pInformation">操作提示信息</param>
    ''' <returns>任务添加成功返回true;添加失败返回false</returns>
    Public Shared Function QueueUserWorkItem(ByVal pCallback As WaitCallback, ByRef pInformation As String) As Boolean
        Dim taskName As String = Guid.NewGuid().ToString()
        Return QueueUserWorkItem(pCallback, Nothing, taskName, BoWeiThreadType.COMMON, pInformation)
    End Function

    ''' <summary>
    ''' 添加任务至线程池
    ''' </summary>
    ''' <param name="pCallback">回调函数的委托</param>
    ''' <param name="pState">回调函数参数</param>
    ''' <param name="pInformation">操作提示信息</param>
    ''' <returns>任务添加成功返回true;添加失败返回false</returns>
    Public Shared Function QueueUserWorkItem(ByVal pCallback As WaitCallback, ByVal pState As Object, ByRef pInformation As String) As Boolean
        Dim taskName As String = Guid.NewGuid().ToString()
        Return QueueUserWorkItem(pCallback, pState, taskName, BoWeiThreadType.COMMON, pInformation)
    End Function

    ''' <summary>
    ''' 添加任务至线程池
    ''' </summary>
    ''' <param name="pCallback">回调函数的委托</param>
    ''' <param name="pTaskName">任务名</param>
    ''' <param name="pInformation">操作提示信息</param>
    ''' <returns>任务添加成功返回true;添加失败返回false</returns>
    Public Shared Function QueueUserWorkItem(ByVal pCallback As WaitCallback, ByVal pTaskName As String, ByRef pInformation As String) As Boolean
        Return QueueUserWorkItem(pCallback, Nothing, pTaskName, BoWeiThreadType.COMMON, pInformation)
    End Function

    ''' <summary>
    ''' 添加任务至线程池
    ''' </summary>
    ''' <param name="pCallback">回调函数的委托</param>
    ''' <param name="pState">回调函数参数</param>
    ''' <param name="pTaskName">任务名</param>
    ''' <param name="pInformation">操作提示信息</param>
    ''' <returns>任务添加成功返回true;添加失败返回false</returns>
    Public Shared Function QueueUserWorkItem(ByVal pCallback As WaitCallback, ByVal pState As Object, ByVal pTaskName As String, ByRef pInformation As String) As Boolean
        Return QueueUserWorkItem(pCallback, pState, pTaskName, BoWeiThreadType.COMMON, pInformation)
    End Function

    ''' <summary>
    ''' 添加任务至线程池
    ''' </summary>
    ''' <param name="pCallback">回调函数的委托</param>
    ''' <param name="pThreadType">处理类型</param>
    ''' <param name="pInformation">操作提示信息</param>
    ''' <returns>任务添加成功返回true;添加失败返回false</returns>
    Public Shared Function QueueUserWorkItem(ByVal pCallback As WaitCallback, ByVal pThreadType As BoWeiThreadType, ByRef pInformation As String) As Boolean
        Dim taskName As String = Guid.NewGuid().ToString()
        Return QueueUserWorkItem(pCallback, Nothing, taskName, pThreadType, pInformation)
    End Function

    ''' <summary>
    ''' 添加任务至线程池
    ''' </summary>
    ''' <param name="pCallback">回调函数的委托</param>
    ''' <param name="pState">回调函数参数</param>
    ''' <param name="pThreadType">处理类型</param>
    ''' <param name="pInformation">操作提示信息</param>
    ''' <returns>任务添加成功返回true;添加失败返回false</returns>
    Public Shared Function QueueUserWorkItem(ByVal pCallback As WaitCallback, ByVal pState As Object, ByVal pThreadType As BoWeiThreadType, ByRef pInformation As String) As Boolean
        Dim taskName As String = Guid.NewGuid().ToString()
        Return QueueUserWorkItem(pCallback, Nothing, taskName, pThreadType, pInformation)
    End Function

    ''' <summary>
    ''' 添加任务至线程池
    ''' </summary>
    ''' <param name="pCallback">回调函数的委托</param>
    ''' <param name="pTaskName">任务名</param>
    ''' <param name="pThreadType">处理类型</param>
    ''' <param name="pInformation">操作提示信息</param>
    ''' <returns>任务添加成功返回true;添加失败返回false</returns>
    Public Shared Function QueueUserWorkItem(ByVal pCallback As WaitCallback, ByVal pTaskName As String, ByVal pThreadType As BoWeiThreadType, ByRef pInformation As String) As Boolean
        Return QueueUserWorkItem(pCallback, Nothing, pTaskName, pThreadType, pInformation)
    End Function

    ''' <summary>添加任务至线程池</summary>
    ''' <param name="pCallback">回调函数的委托</param>
    ''' <param name="pState">回调函数的参数</param>
    ''' <param name="pTaskName">任务名</param>
    ''' <param name="pThreadType">线程类型</param>
    ''' <param name="pInformation">操作提示信息</param>
    ''' <returns>添加任务成功返回true;添加任务失败返回false</returns>
    Public Shared Function QueueUserWorkItem(ByVal pCallback As WaitCallback, ByVal pState As Object, ByVal pTaskName As String, ByVal pThreadType As BoWeiThreadType, ByRef pInformation As String) As Boolean
        Dim callBack As New WaitingCallback(pCallback, pState, pTaskName, pThreadType)

        SyncLock mPoolLock
            If Not mTaskNameList.Contains(pTaskName) Then
                '添加至任务名称队列
                mTaskNameList.Add(pTaskName)
            End If
        End SyncLock

        Select Case CInt(pThreadType)
            Case 0
                'Zip线程处理
                SyncLock mStatProjectLock
                    mStatProjectQueue.Enqueue(callBack)
                End SyncLock
                mStatProjectTaskSignal.AddOne()
                Exit Select

            Case 1

                'Common线程处理
                SyncLock mCommonLock
                    mCommonQueue.Enqueue(callBack)
                End SyncLock
                mCommonTaskSignal.AddOne()
                Exit Select

        End Select
        Return True
    End Function
#End Region


#Region "事件定义"

    Public Delegate Sub NoTaskEventHandle(ByVal eventArg As ThreadPoolNoTaskArg)
    ''' <summary>线程池无任务的事件</summary>
    Public Shared Event NoTaskEvent As NoTaskEventHandle


#End Region

#Region "字段定义"

    ''' <summary>最大自动统计工程量线程数</summary>
    Private Shared mMaxStatProjectCount As Integer = 4
    ''' <summary>最大COMMON线程数</summary>
    Private Shared mMaxCommonThreadCount As Integer = 2

    ''' <summary>自动统计工程量任务控制信号对象</summary>
    Private Shared mStatProjectTaskSignal As TaskSignal
    ''' <summary>COMMON任务控制信号对象</summary>
    Private Shared mCommonTaskSignal As TaskSignal

    ''' <summary>任务队列(ZIP,DQP,ED, COMMON, EDScoreDetail)</summary>
    Private Shared mStatProjectQueue As Queue
    Private Shared mCommonQueue As Queue

    ''' <summary>任务名集合</summary>
    Private Shared mTaskNameList As ArrayList

    ''' <summary>线程池中的运行线程集合</summary>
    Private Shared mWorkingThreadList As ArrayList

    ''' <summary>线程池控制锁</summary>
    Private Shared mPoolLock As New Object()

    ''' <summary>zip控制锁</summary>
    Private Shared mStatProjectLock As New Object()
    ''' <summary>COMMON控制锁</summary>
    Private Shared mCommonLock As New Object()

#End Region

    ''' <summary>回调对象</summary>
    Private Class WaitingCallback
#Region "构造函数"
        ''' <summary>默认构造函数,初始化对象字段</summary>
        ''' <param name="pCallback">回调函数的委托</param>
        ''' <param name="pState">回调函数的参数</param>
        ''' <param name="pName">回调函数的线程名称</param>
        ''' <param name="pThreadType">线程类型</param>
        Public Sub New(ByVal pCallback As WaitCallback, ByVal pState As Object, ByVal pName As String, ByVal pThreadType As BoWeiThreadType)
            mCallback = pCallback
            mState = pState
            mName = pName
            mThreadType = pThreadType
        End Sub
#End Region


#Region "私有字段"

        ''' <summary>回调函数委托</summary>
        Private mCallback As WaitCallback

        ''' <summary>回调函数的参数</summary>
        Private mState As Object

        ''' <summary>回调方法的线程名称</summary>
        Private mName As String

        ''' <summary>线程处理类型</summary>
        Private mThreadType As BoWeiThreadType

#End Region


#Region "属性定义"
        ''' <summary>获取回调函数的委托</summary>
        Public ReadOnly Property Callback() As WaitCallback
            Get
                Return mCallback
            End Get
        End Property

        ''' <summary>获取回调函数的参数</summary>
        Public ReadOnly Property State() As Object
            Get
                Return mState
            End Get
        End Property

        ''' <summary>获取回调线程的优先级</summary>
        Public ReadOnly Property ThreadType() As BoWeiThreadType
            Get
                Return mThreadType
            End Get
        End Property

        ''' <summary>回调方法的线程名称</summary>
        Public ReadOnly Property Name() As String
            Get
                Return mName
            End Get
        End Property
#End Region
    End Class

 

 

#Region "私有方法"

    ''' <summary>初始化线程池</summary>
    Private Shared Sub Initialize()
        '创建任务名称集合
        mTaskNameList = New ArrayList()

        '创建任务队列
        mStatProjectQueue = New Queue()
        mCommonQueue = New Queue()
        '创建运行线程集合
        mWorkingThreadList = New ArrayList()
        '创建任务控制信号对象
        mStatProjectTaskSignal = New TaskSignal()
        mCommonTaskSignal = New TaskSignal()

        For i As Integer = 0 To mMaxStatProjectCount - 1

            '创建自动统计工程量运行线程
            Dim workThread As Thread = Nothing
            workThread = New Thread(New ThreadStart(AddressOf ProcessZIPQueuedItems))
            mWorkingThreadList.Add(workThread)
            workThread.IsBackground = True
            'workThread.ApartmentState = ApartmentState.STA
            workThread.SetApartmentState(ApartmentState.STA)
            workThread.Start()
        Next

        For l As Integer = 0 To mMaxCommonThreadCount - 1

            '创建COMMON运行任务
            Dim workThread As Thread = Nothing
            workThread = New Thread(New ThreadStart(AddressOf ProcessCOMMONQueuedItems))
            mWorkingThreadList.Add(workThread)
            workThread.IsBackground = True
            workThread.Start()
        Next

    End Sub

    ''' <summary>处理自动统计工程量等待任务队列里的任务</summary>
    Private Shared Sub ProcessZIPQueuedItems()
        While True
            '等待一个任务
            mStatProjectTaskSignal.WaitOne()

            While GetWaitingTaskNum(BoWeiTaskType.STATPROJECT) > 10
                Thread.Sleep(20)
            End While

            '获取下一个任务的回调对象
            Dim callback As WaitingCallback = Nothing
            SyncLock mStatProjectLock
                callback = GetNextTask(BoWeiThreadType.STATPROJECT)
            End SyncLock

            If callback IsNot Nothing Then
                '执行对调函数
                Try
                    callback.Callback.Invoke(callback.State)
                Catch e As Exception
                Finally
                    Try
                        SyncLock mPoolLock
                            mTaskNameList.Remove(callback.Name)
                            If mStatProjectQueue.Count = 0 Then

                                Dim noTaskArg As New ThreadPoolNoTaskArg()
                                noTaskArg.TaskType = BoWeiTaskType.STATPROJECT
                                RaiseEvent NoTaskEvent(noTaskArg)


                                GC.Collect()
                            End If
                        End SyncLock
                    Catch
                    End Try
                End Try
            End If
        End While
    End Sub

 

    ''' <summary>处理COMMON等待任务队列里的任务</summary>
    Private Shared Sub ProcessCOMMONQueuedItems()
        While True
            '等待一个任务
            mCommonTaskSignal.WaitOne()

            '获取下一个任务的回调对象
            Dim callback As WaitingCallback = Nothing
            SyncLock mCommonLock
                callback = GetNextTask(BoWeiThreadType.COMMON)
            End SyncLock

            If callback IsNot Nothing Then
                '执行对调函数
                Try
                    callback.Callback.Invoke(callback.State)

                Catch e As Exception
                Finally
                    Try
                        SyncLock mPoolLock
                            mTaskNameList.Remove(callback.Name)
                            If mCommonQueue.Count = 0 Then

                                Dim noTaskArg As New ThreadPoolNoTaskArg()
                                noTaskArg.TaskType = BoWeiTaskType.COMMON
                                RaiseEvent NoTaskEvent(noTaskArg)

                                GC.Collect()
                            End If
                        End SyncLock
                    Catch
                    End Try
                End Try
            End If
        End While
    End Sub

 

    ''' <summary>
    ''' 获取下一个等待任务
    ''' </summary>
    ''' <param name="pThreadType">任务类型</param>
    ''' <returns>返回任务的回调对象</returns>
    Private Shared Function GetNextTask(ByVal pThreadType As BoWeiThreadType) As WaitingCallback
        Dim callback As WaitingCallback = Nothing

        Try
            Select Case pThreadType
                Case BoWeiThreadType.STATPROJECT
                    '自动统计工程量处理
                    If mStatProjectQueue.Count > 0 Then
                        callback = DirectCast(mStatProjectQueue.Dequeue(), WaitingCallback)
                    End If
                    Exit Select
                Case BoWeiThreadType.COMMON

                    'COMMON处理
                    If mCommonQueue.Count > 0 Then
                        callback = DirectCast(mCommonQueue.Dequeue(), WaitingCallback)
                    End If
                    Exit Select

            End Select
        Catch e As Exception
            callback = Nothing
        End Try
        Return callback
    End Function
#End Region
End Class
#End Region

   呵呵..小弟水平有限..如有不足之处..请大虾们指出..

   实践中可以看出线程池技术对于服务器程序的性能改善是显著的。线程池技术在服务器领域有着广泛的应用前景。希望这项技术能够应用到您的多线程服务程序中。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值