可执行任务取消处理线程池
来源:互联网 发布:听写软件 编辑:程序博客网 时间: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,传入处理线程池,取消连接会话对应的任务,进一步取消数据存储事务,而达到数据的回滚的目的。
- 可执行任务取消处理线程池
- 线程池原理(二):可执行任务及其返回值
- 多任务处理:线程池
- 定时任务的线程的取消
- 线程池处理 多个任务
- 模拟线程池,处理异步任务
- Android 使用线程池处理异步任务
- Android使用线程池处理异步任务
- 通过线程池处理多任务
- java线程池中任务异常处理
- 线程池(ThreadPoolExecutor)处理异步任务
- Android使用线程池处理异步任务
- 使用线程池处理异步任务
- JAVA并发-中断处理和任务取消
- Java并发编程——线程池的使用(三)线程池执行任务、取消任务
- 任务,线程和同步(三)之取消架构
- 一种处理多任务的线程池设计
- Android性能优化之使用线程池处理异步任务
- 损失函数
- 模拟jsonp跨域方法
- SCAU1255 Cable master 【待解决】
- 为什么我获取不到这个css样式?js原生获取css样式总结
- 后代、子元素、相邻兄弟选择器
- 可执行任务取消处理线程池
- hduoj1141
- 网站
- linux环境下部署MySQL Connector/C++
- English考研语句第八句
- 一个时间复杂度的问题
- 计算整数的划分可能性算法
- 机器人动力学简化模型(Euler-Lagrange equation)
- java面试题:线程生命周期图解