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

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

在进行多线程异步任务调用时,我们经常会用到.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,传入处理线程池,取消连接会话对应的任务,进一步取消数据存储事务,而达到数据的回滚的目的。

优化这个方法:private View getPopupWindowContentView(LayoutElementParcelable file) { // 一个自定义的布局,作为显示的内容 int layoutId = R.layout.popup_open_file_layout; // 布局ID View contentView = LayoutInflater.from(this).inflate(layoutId, null); // 点击重命名 contentView.findViewById(R.id.open_file_menu_rename).setOnClickListener(v -> { if (mPopupWindow != null) { mPopupWindow.dismiss(); } XLog.tag(TAG).i("popup click:rename"); checkDir(file, 0); }); // 点击删除 contentView.findViewById(R.id.open_file_menu_delete).setOnClickListener(v -> { if (mPopupWindow != null) { mPopupWindow.dismiss(); } XLog.tag(TAG).i("popup click:delete"); checkDir(file, 1); }); // 设置收藏按钮文字 收藏||取消收藏 String collectPath = ""; if (mCollects != null) { collectPath = mCollects.get(file.desc); } if (TextUtils.isEmpty(collectPath)) { collectPath = ""; } // 点击 收藏||取消收藏 TextView open_file_menu_collect = contentView.findViewById(R.id.open_file_menu_collect); String finalCollectPath = collectPath; open_file_menu_collect.setOnClickListener(v -> { if (mPopupWindow != null) { mPopupWindow.dismiss(); } if (finalCollectPath.equals(file.desc)) { XLog.tag(TAG).i("popup click:unCollect"); } else { XLog.tag(TAG).i("popup click:collect"); saveFileBrowseRecord(file); } }); if (collectPath.equals(file.desc)) { open_file_menu_collect.setText(getString(R.string.file_browser_un_collect)); } else { open_file_menu_collect.setText(getString(R.string.file_browser_collect)); } if (mTransferType == U_FTP_TO_FAB_FTP || mTransferType == FTP_U) { open_file_menu_collect.setVisibility(View.VISIBLE); } else { open_file_menu_collect.setVisibility(View.GONE); } return contentView; }
06-08
可以考虑对以下几个方面进行优化: 1. 使用静态内部类实现 OnClickListener,避免每次都创建新的对象。 2. 使用 Lambda 表达式替代匿名内部类,使代码更简洁。 3. 对于重复的逻辑可以进行方法封装,避免重复代码。 4. 对于重复的 View 查找,可以在方法外部进行缓存,避免重复查找。 5. 对于频繁调用的方法,可以使用局部变量进行缓存,避免多次调用。 下面是优化后的代码: private View getPopupWindowContentView(LayoutElementParcelable file) { // 一个自定义的布局,作为显示的内容 int layoutId = R.layout.popup_open_file_layout; // 布局ID View contentView = LayoutInflater.from(this).inflate(layoutId, null); // 点击重命名 contentView.findViewById(R.id.open_file_menu_rename).setOnClickListener(OnRenameClickListener.INSTANCE); // 点击删除 contentView.findViewById(R.id.open_file_menu_delete).setOnClickListener(OnDeleteClickListener.INSTANCE); // 点击 收藏||取消收藏 TextView open_file_menu_collect = contentView.findViewById(R.id.open_file_menu_collect); open_file_menu_collect.setOnClickListener(OnCollectClickListener.INSTANCE); // 设置收藏按钮文字 收藏||取消收藏 String collectPath = mCollects != null ? mCollects.get(file.desc) : ""; String collectText = collectPath.equals(file.desc) ? getString(R.string.file_browser_un_collect) : getString(R.string.file_browser_collect); open_file_menu_collect.setText(collectText); // 设置收藏按钮可见性 open_file_menu_collect.setVisibility(mTransferType == U_FTP_TO_FAB_FTP || mTransferType == FTP_U ? View.VISIBLE : View.GONE); return contentView; } private static class OnRenameClickListener implements View.OnClickListener { static final OnRenameClickListener INSTANCE = new OnRenameClickListener(); @Override public void onClick(View v) { if (mPopupWindow != null) { mPopupWindow.dismiss(); } XLog.tag(TAG).i("popup click:rename"); checkDir(file, 0); } } private static class OnDeleteClickListener implements View.OnClickListener { static final OnDeleteClickListener INSTANCE = new OnDeleteClickListener(); @Override public void onClick(View v) { if (mPopupWindow != null) { mPopupWindow.dismiss(); } XLog.tag(TAG).i("popup click:delete"); checkDir(file, 1); } } private static class OnCollectClickListener implements View.OnClickListener { static final OnCollectClickListener INSTANCE = new OnCollectClickListener(); @Override public void onClick(View v) { if (mPopupWindow != null) { mPopupWindow.dismiss(); } boolean isCollected = finalCollectPath.equals(file.desc); String logText = isCollected ? "popup click:unCollect" : "popup click:collect"; XLog.tag(TAG).i(logText); if (!isCollected) { saveFileBrowseRecord(file); } } }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值