基于ThreadPool的简单工作管理器

  有这样的场景,淘宝开放平台上有销售订单API,销售订单金额API,商品上下架API,退款API等各种开放的 API,稍微有点规模的商家都会自己开发基于淘宝平台的信息管理系统,里面会涉及到订单管理,采购管理,库存管理,售后管理等,这些管理系统里面的数据都是通过API获取,或者通过API推送到淘宝平台上,这些系统的好处就是避免工作人员直接在淘宝后台进行各项操作。

  基于上面的情况,那么自然会有很多后台程序来跑这些 API,刚开始我是这样设计的。

  

在一个后台程序里面开几个线程,每个线程对应几个API,这样也能够满足日常需求,但是随着业务量增大,会有各种数据或者任务需要处理,这个时候上面的程序也能满足需求,但是每次都要修改程序,然后在发布,实在是有些头疼。后来我就想,能不能开发一个管理平台,来自动管理这些任务,什么时候想停止任务,直接在配置管理网站上点一下按钮,想开启也是一样操作,如果推出这样的一个管理平台,那么像管理这种业务数据的活可以直接丢给店铺管理人员。

  经过一番思考,想到了这样一种方案,先看图。

  

上面的图可以很清晰看出工作管理模型。其实到这个时候,最最关心还是工作管理器的内核到底是怎样设计的?那我就说说我的思路是怎样的。

  首先是工作任务运行时间的设计,因为有的API是需要白天运行的有的是晚上闲时运行的,有的是7*24小时不间断运行的,那么我们可以设计这样的一个枚举,命名WorkType,具体内容是:

 public enum WorkType
 {
        ALLWork = 1,

        WorkTime = 2,

        Morning = 3,

        Night = 4
 }

 

ALLWork 的运行时间是全天,WorkTime的运行时间是早上9点到晚上22点,Morning的运行时间是凌晨3点到早上9点,Night的运行时间是晚上22点到凌晨3点,相信这几个时间区域很多开发同事都会涉及到的。

  然后是工作线程类WorkThread,将它定义为一个抽象类,里面含有一个抽象方法WorkRun,每一个详细的任务类都会继承WorkThread类,实现抽象方法,也就是说,每个任务的业务处理逻辑都是在WorkRun方法里面实现的。因为上面提到了任务的运行时间区间,那么我们在初始化一个继承WorkThread类的时候,会设置它的运行时间区间。然后在这个抽象类中还还有一个方法,它的作用就是将实现了WorkThread的类丢到ThreadPool里面,看看具体的实现代码。

public abstract class WorkThread
 {
        private int index;

        public WorkThread(int Step,WorkType worktype)
        {
            this.WorkType = worktype;
            this.Step = Step;
            this.index = Step;
        }

        public int Step { get;  set; }

        public WorkType WorkType { get;  set; }

        public bool HasWork
        {
            get
            {
                bool result = false;
                switch (WorkType)
                {
                    case WorkType.Morning:
                        result = index == Step &&  3<=DateTime.Now.Hour && DateTime.Now.Hour<=9 ? true : false;
                        break;
                    case WorkType.WorkTime:
                        result = index == Step && 9 <= DateTime.Now.Hour && DateTime.Now.Hour <= 22 ? true : false;
                        break;
                    case WorkType.Night:
                        result = index == Step && 22 <= DateTime.Now.Hour && DateTime.Now.Hour <= 3 ? true : false;
                        break;

                    case WorkType.ALLWork:
                    default:
                        result = index == Step  ? true : false;
                        break;

                }
                return result;
            }
        }

        public abstract void WorkRun(object ob);
       
        public void Run()
        {
            ThreadPool.QueueUserWorkItem(new WaitCallback(WorkRun));
            index = 0;
        }

        public void AddStep()
        {
            index += 1;
        }
 }

  那么具体的任务类如下。

 public class TestA : WorkThread
 {
        public TestA(int step, WorkType type)
            : base(step, type)
        { }

        public override void WorkRun(object ob)
        {
            Console.WriteLine(string.Format("我是A小姐,我开始工作了。时间:{0}", DateTime.Now));
        }
 }

  其实到这里了,有的人会想到,那我们怎么来管理这些WorkThread类了,这里我们专门有一个类来管理WorkThread,这里命名为WorkManager。这个类里面的结构就相当简单了。看到上面的模型图,可以猜出一些端倪。里面专门定义了一个字典项,用来存储每一个WorkThread,它是ConcurrentDictionary,表示可由多个线程同时访问的键值对的线程安全集合。管理类里面还定义了4个方法,增加删除WorkThread,开始结束WorkThread。具体看下面的代码。

public class WorkManager
{
        static readonly ConcurrentDictionary<string, WorkThread> WorkCache = 
            new ConcurrentDictionary<string, WorkThread>();

        public int WorkCount 
        {
            get { return WorkCache.Count; }
        }

        public void AddWork(WorkThread workThread)
        {
            WorkCache.TryAdd(workThread.GetType().FullName, workThread);
        }

        public void RemoveWork(string workThreadId)
        {
            var obj = WorkCache[workThreadId];
            if(obj != null)
                WorkCache.TryRemove(workThreadId, out obj);
        }

        public void StartWork()
        {
            Action action = () =>
            {
                while (true)
                {
                    foreach (KeyValuePair<string, WorkThread> work in WorkCache)
                    {
                        if (work.Value.HasWork)
                        {
                            work.Value.Run();
                        }
                        else
                        {
                            work.Value.AddStep();
                        }
                    }

                    Thread.Sleep(5000);
                }
            };
            action.BeginInvoke(cb => action.EndInvoke(cb), null);
        }

        public void EndWork()
        {
            Action action = () =>
            {
                WorkCache.Clear();
            };
            action.BeginInvoke(cb => action.EndInvoke(cb), null);
        }

}

代码是不是很简单,到这里位置,工作管理的内核代码全部上完了,那我们该怎么调用了,看看下面调用代码。

            Console.Title = "工作管理器";

            WorkManager manager = new WorkManager();
            manager.AddWork(new TestA(1, WorkType.ALLWork));
            manager.AddWork(new TestB(1, WorkType.ALLWork));
            manager.StartWork();

            Console.WriteLine("1.全部开始工作");
            Thread.Sleep(15 * 1000);

            manager.EndWork();
            Console.WriteLine("2.全部卸载");

            Thread.Sleep(10 * 1000);
            manager.AddWork(new TestB(1, WorkType.ALLWork));
            Console.WriteLine("3.加入B");

            Console.Read();    

看一下运行效果图:

  大家看完之后是不是觉得很简单,不过有什么疑问可以在这里留言,谢谢。

  示例代码下载:https://files.cnblogs.com/wucj/WorkManager.rar

 

posted @ 2013-05-26 21:41  布衣人老白  阅读(473)  评论(1编辑  收藏  举报