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

来源:互联网 发布:听写软件 编辑:程序博客网 时间:2024/06/06 09:53

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

在进行多线程异步任务调用时,我们经常会用到.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 0