可执行任务取消处理线程池

周末闲来无事,把思考了很久的一个线程池处理算法,实现了,总结了一下设计的思路和设计的初衷。

在进行多线程异步任务调用时,我们经常会用到.net中的线程池System.Threading.ThreadPool.QueueUserWorkItem,随着微软在线程池调度算法上的优化,线程池的效率和智能化等方面,越来越高,但是该线程池,也存在操作的缺陷,比如发起一个异步的大数据保存操作,执行数据保存可能需要耗时时间很长,在此过程中,用户可能发现前端数据输入有问题,需要取消操作,如果用默认的线程池,进行异步操作,由于线程池中的线程采用智能分配和调度,我们没法取消对应的线程操作,数据保存还在异步线程中执行着,最终得到不是需要的结果。

如果需要对任务可取消操作,又不丢失线程池的灵活性和方便性,我们需要自定义可执行任务取消处理的线程池,调用接口与原线程池一致,但是增加了取消任务的调用操作。

自定义线程的设计思路是,利用托管线程消息队列,负责所有的异步消息的分发和路由,同时利用托管线程消息队列,进行资源的管理,因为托管线程消息队列,已执行了消息的线程间同步,策略算法的处理,就不需要线程间的二次同步处理。

考虑到该线程池的场合,是分场景的,因此没有做成全局静态入口线程池,但可在调用处独立实例化封装为全局静态入口线程池。

整个设计流程思路:

核心调度算法代码,核心算法中用到了周期性的消息处理队列,这个在其他文章,介绍线程池时,有介绍,此处不再描述:

/// <summary>
    /// 手工,带队列缓冲,可取消任务处理线程池
    /// </summary>
    public class ManualQueueThreadPool
    {
        /// <summary>
        /// 容器托管线程
        /// </summary>
        private ITimerMessageFIFO dockerMessageFIFO = null;
        /// <summary>
        /// 等待被执行的任务列表
        /// </summary>
        private List<ManualTask> waitManualTaskList = new List<ManualTask>();
        /// <summary>
        /// 工作线程列表
        /// </summary>
        private List<WorkThreadInfo> workThreadInfoList = new List<WorkThreadInfo>();
        /// <summary>
        /// 最大工作线程数量
        /// </summary>
        private int maxWorkThreadCount = 10;
        /// <summary>
        /// 最大工作线程数量
        /// </summary>
        public int MaxWorkThreadCount
        {
            get 
            {
                return maxWorkThreadCount;
            }
        }
        /// <summary>
        /// 最大的自由线程数量
        /// </summary>
        private int maxFreeThreadCount = 2;
        /// <summary>
        /// 最大空闲线程数量,空闲线程,用于随时执行新的调度
        /// </summary>
        public int MaxFreeThreadCount
        {
            get 
            {
                return maxFreeThreadCount;
            }
        }
        private int initWorkThreadCount = 3;
        /// <summary>
        /// 默认启动初始化线程数量
        /// </summary>
        public int InitWorkThreadCount
        {
            get 
            {
                return initWorkThreadCount;
            }
        }
        private int freeWorkThreadCollectTimeOut = 10;
        /// <summary>
        /// 空闲线程,回收处理超时时间,单位是分钟
        /// </summary>
        public int FreeWorkThreadCollectTimeOut
        {
            get 
            {
                return freeWorkThreadCollectTimeOut;
            }
        }
        /// <summary>
        /// 是否正在关闭
        /// </summary>
        private volatile bool onClosing = false;
        /// <summary>
        /// 创建线程池
        /// </summary>
        /// <param name="initWorkThreadCount">默认启动初始化线程数量,默认3个</param>
        /// <param name="maxFreeThreadCount">最大空闲线程数量,空闲线程,用于随时执行新的调度,默认2个</param>
        /// <param name="maxWorkThreadCount">最大工作线程数量,默认10个</param>
        /// <param name="freeWorkThreadCollectTimeOut">空闲线程回收超时时间,单位是分钟,默认10分钟</param>
        /// <returns>
        /// 返回创建的线程池
        /// </returns>
        public static ManualQueueThreadPool Create(int initWorkThreadCount = 3, int maxFreeThreadCount = 2, int maxWorkThreadCount = 10,int freeWorkThreadCollectTimeOut=10)
        {
            ManualQueueThreadPool manualQueueThreadPool = new ManualQueueThreadPool();
            manualQueueThreadPool.initWorkThreadCount = initWorkThreadCount;
            manualQueueThreadPool.maxFreeThreadCount = maxFreeThreadCount;
            manualQueueThreadPool.maxWorkThreadCount = maxWorkThreadCount;
            manualQueueThreadPool.freeWorkThreadCollectTimeOut = freeWorkThreadCollectTimeOut;
            return manualQueueThreadPool;
        }
        private ManualQueueThreadPool()
        { 
        
        }
        /// <summary>
        /// 启动
        /// </summary>
        public void Open()
        {
            this.InnerStartDocker();
            ManualTaskCommandInfo taskCommandInfo = new ManualTaskCommandInfo(ManualTaskCommand.StartWorkThreads);
            this.PushDockerMessageFIFO(taskCommandInfo);
        }
        /// <summary>
        /// 关闭
        /// </summary>
        public void Close()
        {
            this.onClosing = true;
            ManualTaskCommandInfo taskCommandInfo = new ManualTaskCommandInfo(ManualTaskCommand.CloseWorkThreads);
            this.PushDockerMessageFIFO(taskCommandInfo);
            this.InnerStopDocker();
        }
        /// <summary>
        /// 内部启动
        /// </summary>
        private void InnerStartDocker()
        {
            if (dockerMessageFIFO == null)
            {
                dockerMessageFIFO = TimerMessageFIFO.Create(new ManualTimer.TimerParameters(200, 5000), MessageFIFOType.LockMessageFIFO);//5秒钟一次进行资源查询
                dockerMessageFIFO.MessageCallBack += dockerMessageFIFO_MessageCallBack;
                dockerMessageFIFO.SignalCallBack += dockerMessageFIFO_SignalCallBack;
            }
            if (dockerMessageFIFO != null)
            {
                if (dockerMessageFIFO.IsRunning() == false)
                {
                    dockerMessageFIFO.Start();
                }
            }
        }
        /// <summary>
        /// 启动工作线程列表
        /// </summary>
        private void InnerStartWorkThreadList()
        {
            for (int i = 0; i < initWorkThreadCount; i++)
            {
                IMessageFIFO workMessageFIFO = MessageFIFOFactory.Create(MessageFIFOType.LockMessageFIFO);
                workMessageFIFO.Excute += workMessageFIFO_Excute;
                workMessageFIFO.Start();
                WorkThreadInfo workThreadInfo = new WorkThreadInfo(workMessageFIFO);
                this.workThreadInfoList.Add(workThreadInfo);
            }
        }
        /// <summary>
        /// 执行具体的工作线程处理
        /// </summary>
        /// <param name="obj"></param>
        private void workMessageFIFO_Excute(object obj)
        {
            if (obj is ManualTask)
            {
                ManualTask task = (ManualTask)obj;
                task.WaitCallback.Invoke(task.Data);
            }
        }
        /// <summary>
        /// 停止工作线程列表
        /// </summary>
        private void InnerStopWorkThreadList()
        {
            if (this.workThreadInfoList==null || this.workThreadInfoList.Count == 0)
            {
                return;
            }
            for (int i = 0; i < this.workThreadInfoList.Count; i++)
            {
                WorkThreadInfo info = this.workThreadInfoList[i];
                if (info.WorkThread != null && info.WorkThread.IsOpened == true)
                {
                    info.WorkThread.ForceStop();
                }
            }
            this.workThreadInfoList.Clear();
        }
        /// <summary>
        /// 压入数据到内部消息处理队列
        /// </summary>
        /// <param name="data">数据</param>
        private void PushDockerMessageFIFO(object data)
        {
            if (dockerMessageFIFO == null || dockerMessageFIFO.IsRunning() == false)
            {
                if (onClosing == false)
                {
                    InnerStartDocker();
                }
            }
            if (dockerMessageFIFO != null && dockerMessageFIFO.IsRunning() == true)
            {
                dockerMessageFIFO.PostData(data);
            }
        }
        /// <summary>
        /// 周期性的信号反馈,用于将缓存队列中的待处理任务,泵入工作线程,或对空闲线程进行释放
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="data"></param>
        private void dockerMessageFIFO_SignalCallBack(object sender, bool data)
        {
            #region 释放掉,已关闭的工作线程
            this.workThreadInfoList.RemoveAll(delegate(WorkThreadInfo tempWorkThreadInfo)
            {
                return tempWorkThreadInfo.WorkThread == null || tempWorkThreadInfo.WorkThread.IsOpened == false; 
            });
            #endregion
            #region 将缓存队列中的数据压入工作线程组
            if (this.waitManualTaskList.Count > 0)//从缓存队列中获取
            {
                for (int i = 0; i < this.workThreadInfoList.Count; i++)
                {
                    WorkThreadInfo tempWorkThreadInfo = this.workThreadInfoList[i];
                    if (tempWorkThreadInfo.WorkThread != null
                        && tempWorkThreadInfo.WorkThread.IsOpened == true
                        && tempWorkThreadInfo.WorkThread.WaitExcuteTaskCount <= 0)
                    {
                        if (this.waitManualTaskList.Count > 0)
                        {
                            ManualTask tempManualTask = this.waitManualTaskList[0];
                            tempWorkThreadInfo.PostTask(tempManualTask);
                            this.waitManualTaskList.Remove(tempManualTask);
                        }
                        else
                        {
                            break;
                        }
                    }
                }
            }
            #endregion
            #region 构建新的线程,用于处理缓存队列中的数据
            if (this.waitManualTaskList.Count > 0)
            {
                if (this.workThreadInfoList.Count >= maxWorkThreadCount)//线程已达到最大用量,还存在未执行的任务
                {
                    return;
                }
                for (int i = 0; i < this.waitManualTaskList.Count; i++)
                {
                    ManualTask tempManualTask = this.waitManualTaskList[i];
                    if (this.workThreadInfoList.Count >= maxWorkThreadCount)
                    {
                        return;
                    }
                    IMessageFIFO workMessageFIFO = MessageFIFOFactory.Create(MessageFIFOType.LockMessageFIFO);
                    workMessageFIFO.Excute += workMessageFIFO_Excute;
                    workMessageFIFO.Start();
                    WorkThreadInfo newWorkThreadInfo = new WorkThreadInfo(workMessageFIFO);
                    this.workThreadInfoList.Add(newWorkThreadInfo);
                    newWorkThreadInfo.PostTask(tempManualTask);
                }
            }
            #endregion
            #region 线程使用未饱和,多余的空闲线程进行资源释放
            int tempFreeThreadCount = 0;
            List<WorkThreadInfo> freeWorkThreadInfoList = null;
            for (int i = 0; i < this.workThreadInfoList.Count; i++)
            {
                WorkThreadInfo workThreadInfo = this.workThreadInfoList[i];
                if (workThreadInfo.WorkThread != null
                    && workThreadInfo.WorkThread.IsOpened == true
                    && workThreadInfo.WorkThread.WaitExcuteTaskCount <= 0
                    && (DateTime.Now - workThreadInfo.LastWorkTime).TotalMinutes > freeWorkThreadCollectTimeOut)
                {
                    tempFreeThreadCount += 1;
                    if (this.workThreadInfoList.Count > (initWorkThreadCount + maxFreeThreadCount)
                        && tempFreeThreadCount > maxFreeThreadCount)
                    {
                        if (freeWorkThreadInfoList == null)
                        {
                            freeWorkThreadInfoList = new List<WorkThreadInfo>();
                        }
                        freeWorkThreadInfoList.Add(workThreadInfo);
                    }
                }
            }
            if (freeWorkThreadInfoList != null)
            {
                for (int i = 0; i < freeWorkThreadInfoList.Count; i++)
                {
                    WorkThreadInfo workThreadInfo = freeWorkThreadInfoList[i];
                    workThreadInfo.WorkThread.Stop();
                    this.workThreadInfoList.Remove(workThreadInfo);
                }
            }
            #endregion
        }
        /// <summary>
        /// 消息处理回调
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="data"></param>
        private void dockerMessageFIFO_MessageCallBack(object sender, object data)
        {
            if (data is ManualTask)//泵入任务到工作线程
            {
                ManualTask task = (ManualTask)data;
                WorkThreadInfo workThreadInfo = null;
                for (int i = 0; i < this.workThreadInfoList.Count; i++)
                {
                    WorkThreadInfo tempWorkThreadInfo = this.workThreadInfoList[i];
                    if (tempWorkThreadInfo.WorkThread != null
                        && tempWorkThreadInfo.WorkThread.IsOpened == true
                        && tempWorkThreadInfo.WorkThread.WaitExcuteTaskCount <= 0)
                    {
                        workThreadInfo = tempWorkThreadInfo;
                        break;
                    }
                }
                if (workThreadInfo != null)
                {
                    workThreadInfo.PostTask(task);
                    return;
                }
                if (workThreadInfoList.Count >= maxWorkThreadCount)
                {
                    this.waitManualTaskList.Add(task);
                    return;
                }
                IMessageFIFO workMessageFIFO = MessageFIFOFactory.Create(MessageFIFOType.LockMessageFIFO);
                workMessageFIFO.Excute += workMessageFIFO_Excute;
                workMessageFIFO.Start();
                WorkThreadInfo newWorkThreadInfo = new WorkThreadInfo(workMessageFIFO);
                this.workThreadInfoList.Add(newWorkThreadInfo);
                newWorkThreadInfo.PostTask(task);
            }
            else if (data is ManualTaskCommandInfo)
            {
                ManualTaskCommandInfo manualTaskCommandInfo = (ManualTaskCommandInfo)data;
                if (manualTaskCommandInfo.ManualTaskCommand == ManualTaskCommand.StartWorkThreads)//初始化工作线程组
                {
                    this.InnerStartWorkThreadList();
                }
                else if (manualTaskCommandInfo.ManualTaskCommand == ManualTaskCommand.CloseWorkThreads)//结束所有工作线程
                {
                    this.InnerStopWorkThreadList();
                }
                else if (manualTaskCommandInfo.ManualTaskCommand == ManualTaskCommand.CancelTask)//取消某一个任务
                {
                    if (this.waitManualTaskList.Count > 0)//从缓存队列中获取
                    {
                        ManualTask manualTask = this.waitManualTaskList.Find(delegate(ManualTask tempManualTask) 
                        {
                            return tempManualTask.TaskID.Equals(manualTaskCommandInfo.TaskID, StringComparison.OrdinalIgnoreCase); 
                        });
                        if (manualTask != null)
                        {
                            this.waitManualTaskList.Remove(manualTask);
                            return;
                        }
                    }
                    if (this.workThreadInfoList.Count > 0)//从工作线程组中获取
                    {
                        WorkThreadInfo workThreadInfo = this.workThreadInfoList.Find(delegate(WorkThreadInfo tempWorkThreadInfo)
                        {
                            return tempWorkThreadInfo.TaskID.Equals(manualTaskCommandInfo.TaskID, StringComparison.OrdinalIgnoreCase);
                        });
                        if (workThreadInfo != null)
                        {
                            workThreadInfo.WorkThread.ForceStop();
                        }
                        this.workThreadInfoList.Remove(workThreadInfo);
                    }
                }
            }
        }
        /// <summary>
        /// 内部停止
        /// </summary>
        private void InnerStopDocker()
        {
            if (dockerMessageFIFO != null && dockerMessageFIFO.IsRunning() == true)
            {
                dockerMessageFIFO.Stop();
            }
            dockerMessageFIFO = null;
        }
        /// <summary>
        /// 压入处理请求到线程池
        /// </summary>
        /// <param name="taskID">唯一任务ID</param>
        /// <param name="waitCallBack">回调委托</param>
        /// <param name="data">数据</param>
        public void PushTaskToQueue(string taskID,WaitCallback waitCallBack,object data)
        {
            ManualTask task = new ManualTask(taskID, waitCallBack, data);
            this.PushDockerMessageFIFO(task);
        }
        /// <summary>
        /// 取消任务
        /// </summary>
        /// <param name="taskID">任务ID</param>
        public void CancelTask(string taskID)
        {
            ManualTaskCommandInfo cancelManualTaskCommandInfo = new ManualTaskCommandInfo(ManualTaskCommand.CancelTask);
            cancelManualTaskCommandInfo.TaskID = taskID;
            this.PushDockerMessageFIFO(cancelManualTaskCommandInfo);
        }
    }


整个调度算法写完之后,用于替换,Trace.RMI.Server中间件中的,数据处理部分,具体应用场景为,客户端发起TCP会话连接,服务器端监听到连接会话时,将每一次的处理任务数据,发送到线程池,在线程池中具体执行,服务器端的业务处理,监听会话线程结束,监听会话回归连接池。回调时,在处理线程调用会话ID,重新将连接会话调入业务处理线程,进行回调结果处理。由于服务器端的业务处理,可能时间比较长,客户端在异步等待窗口等待,当用户因为等待时间太长,需要取消操作时,服务器端的业务处理,就无法通过连接会话的取消而取消了。新的场景中,通过对应的连接会话ID,传入处理线程池,取消连接会话对应的任务,进一步取消数据存储事务,而达到数据的回滚的目的。

  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值