程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> .NET網頁編程 >> C# >> C#入門知識 >> 你程序會做飯嘛?我能!,程序會做飯

你程序會做飯嘛?我能!,程序會做飯

編輯:C#入門知識

你程序會做飯嘛?我能!,程序會做飯


別嘲笑這個標題。我想了很久。有點“投機取巧”的功效吧!

程序當然不能做飯。

之前的我們的系列文章,介紹, 多線程執行,任務派發。定時器執行。腳本加載。程序狀態機。

這些都是零零散散,或者說都是模塊化介紹,以及模塊測試用例。

那麼今天我們就來模擬正常程序流程。使用上述的功能性代碼完成流程。

當然今天的測試用例程序肯定和做飯有關。今天要做的是模擬一個餐廳的流程。

完成 客人入座 -> 點菜 -> 等待就餐 -> 就餐 -> 等待結賬 -> 結賬 -> 離開.

期間包括 等待就餐 添加茶水,就餐的添加茶水,添加米飯等隨機事件

新建控制台項目:

Sz.Network.DiningRoom 用於存放主文件項目

類庫

Sz.Network.DiningRoom.Scripts  用於存放腳本文件項目

 

我們先來初始化餐廳。

/**
 * 
 * @author 失足程序員
 * @Blog http://www.cnblogs.com/ty408/
 * @mail [email protected]
 * @phone 13882122019
 * 
 */
namespace Sz.Network.DiningRoom
{

    /// <summary>
    /// 
    /// </summary>
    public class 餐廳
    {

        private static 餐廳 instance = new 餐廳();

        public static 餐廳 GetInstance { get { return instance; } }

        public long 全局線程 = 0;
        public long 廚師s = 0;
        public long 傳菜員s = 0;
        public long 服務員s = 0;
        public long 配菜員s = 0;
        public long 收銀員s = 0;
        public long 洗菜員s = 0;

        public 客人[] table = null;


        public void Init(int tableSize)
        {
            Logger.Info("初始化餐廳");
            //所有的工作人員都是一個線程
            全局線程 = ThreadPool.ThreadManager.GetInstance.GetThreadModel(new ThreadPool.ThreadModel("全局線程", 1));
            //所有的工作人員都是一個線程
            廚師s = ThreadPool.ThreadManager.GetInstance.GetThreadModel(new ThreadPool.ThreadModel("廚師", 3));
            //所有的工作人員都是一個線程
            傳菜員s = ThreadPool.ThreadManager.GetInstance.GetThreadModel(new ThreadPool.ThreadModel("傳菜員", 5));
            //所有的工作人員都是一個線程
            服務員s = ThreadPool.ThreadManager.GetInstance.GetThreadModel(new ThreadPool.ThreadModel("服務員", 5));
            //所有的工作人員都是一個線程
            配菜員s = ThreadPool.ThreadManager.GetInstance.GetThreadModel(new ThreadPool.ThreadModel("配菜員", 3));
            //所有的工作人員都是一個線程
            收銀員s = ThreadPool.ThreadManager.GetInstance.GetThreadModel(new ThreadPool.ThreadModel("收銀員", 1));
            //所有的工作人員都是一個線程
            洗菜員s = ThreadPool.ThreadManager.GetInstance.GetThreadModel(new ThreadPool.ThreadModel("洗菜員", 2));

            table = new 客人[tableSize];
            for (int i = 0; i < tableSize; i++)
            {
                Logger.Info("初始化餐桌 " + (i + 1) + " 號桌");
            }

        }
    }
}

每一個工作人員都是一個線程。模擬線程。

我們這裡,餐廳配置:"廚師", 3 "傳菜員", 5  "服務員", 5  "配菜員", 3  "收銀員", 1  "洗菜員", 2

各個環節的人員都不相同,且每一步操作都不進相同。

接下來我們初始化客人,

/**
 * 
 * @author 失足程序員
 * @Blog http://www.cnblogs.com/ty408/
 * @mail [email protected]
 * @phone 13882122019
 * 
 */
namespace Sz.Network.DiningRoom
{
    public class 客人
    {

        public static EnumStatus Status入座 = new EnumStatus(1 << 0, 0x000000);
        public static EnumStatus Status取消 = new EnumStatus(1 << 1, 0x000000);
        public static EnumStatus Status點菜 = new EnumStatus(1 << 2, 0x000000);
        public static EnumStatus Status就餐 = new EnumStatus(1 << 3, 0x000000);
        public static EnumStatus Status結賬中 = new EnumStatus(1 << 4, 0x000000);
        public static EnumStatus Status等待就餐 = new EnumStatus(1 << 5, 0x000000);
        public static EnumStatus Status等待結賬 = new EnumStatus(1 << 6, 0x000000);

        /// <summary>
        /// 存儲臨時數據的
        /// </summary>
        public ObjectAttribute TempAttribute = new ObjectAttribute();
        /// <summary>
        /// 客人當前的狀態
        /// </summary>
        public EnumStatus Staus = new EnumStatus(0, 0x000000);

        public List<菜肴> 菜肴s = new List<菜肴>();

        public int TableID { get; set; }

        /// <summary>
        /// 每一個客人的隨機標識
        /// </summary>
        public string guidID { get; set; }

        public 客人(int tableID)
        {
            guidID = Guid.NewGuid().ToString().Replace("-", "");
            this.TableID = tableID;
            Staus |= Status入座;
            Show();
        }

        public void 點菜()
        {
            ThreadPool.ThreadManager.GetInstance.AddTask(餐廳.GetInstance.服務員s, new Task點菜(this));
            Task隨機事件發生處理器 task = new Task隨機事件發生處理器(this.TableID + " 號桌客人 上碗筷");
            ThreadPool.ThreadManager.GetInstance.AddTask(餐廳.GetInstance.服務員s, task);
        }

        public void Add點菜(菜肴 菜)
        {
            菜肴s.Add(菜);
            ThreadPool.ThreadManager.GetInstance.AddTask(餐廳.GetInstance.洗菜員s, new Task菜(this, 菜));
        }

        public void Show()
        {
            string 狀態 = "";
            if (Staus.HasFlag(Status入座))
            {
                狀態 = "入座";
            }
            else if (Staus.HasFlag(Status取消))
            {
                狀態 = "取消";
            }
            else if (Staus.HasFlag(Status點菜))
            {
                狀態 = "點菜";
            }
            else if (Staus.HasFlag(Status等待就餐))
            {
                狀態 = "等待就餐";
            }
            else if (Staus.HasFlag(Status就餐))
            {
                狀態 = "就餐";
            }
            else if (Staus.HasFlag(Status等待結賬))
            {
                狀態 = "等待結賬";
            }
            else if (Staus.HasFlag(Status結賬中))
            {
                狀態 = "結賬中";
            }
            Logger.Info(this.TableID + " 號桌子 客人 " + this.guidID + " 當前狀態:" + 狀態);
        }

    }
}

 

初始化菜肴

/**
 * 
 * @author 失足程序員
 * @Blog http://www.cnblogs.com/ty408/
 * @mail [email protected]
 * @phone 13882122019
 * 
 */
namespace Sz.Network.DiningRoom
{
    public class 菜肴
    {

        public static EnumStatus Status點菜 = new EnumStatus(1 << 0, 0x000000);
        public static EnumStatus Status取消 = new EnumStatus(1 << 1, 0x000000);
        public static EnumStatus Status洗菜 = new EnumStatus(1 << 2, 0x000000);
        public static EnumStatus Status配菜 = new EnumStatus(1 << 3, 0x000000);
        public static EnumStatus Status炒菜 = new EnumStatus(1 << 4, 0x000000);
        public static EnumStatus Status傳菜 = new EnumStatus(1 << 5, 0x000000);
        public static EnumStatus Status就餐 = new EnumStatus(1 << 6, 0x000000);
        public static EnumStatus Status結束就餐 = new EnumStatus(1 << 7, 0x000000);


        public string Name { get; private set; }


        public EnumStatus Staus = new EnumStatus(0, 0x000000);
        /// <summary>
        /// 存儲臨時數據的
        /// </summary>
        public ObjectAttribute TempAttribute = new ObjectAttribute();

        public 菜肴(string name)
        {
            this.Name = name;
            Staus |= Status點菜;
            Show();
        }

        public void Show()
        {
            string 狀態 = "";
            if (Staus.HasFlag(Status點菜))
            {
                狀態 = "點菜";
            }
            else if (Staus.HasFlag(Status取消))
            {
                狀態 = "取消";
            }
            else if (Staus.HasFlag(Status洗菜))
            {
                狀態 = "洗菜";
            }
            else if (Staus.HasFlag(Status配菜))
            {
                狀態 = "配菜";
            }
            else if (Staus.HasFlag(Status炒菜))
            {
                狀態 = "炒菜";
            }
            else if (Staus.HasFlag(Status傳菜))
            {
                狀態 = "傳菜";
            }
            else if (Staus.HasFlag(Status就餐))
            {
                狀態 = "就餐";
            }
            Logger.Info(this.Name + " 當前狀態:" + 狀態);
        }

    }
}

我們需要創建一個定時器任務,對餐桌和客人進行狀態監測和隨機事件發生器

/**
 * 
 * @author 失足程序員
 * @Blog http://www.cnblogs.com/ty408/
 * @mail [email protected]
 * @phone 13882122019
 * 
 */
namespace Sz.Network.DiningRoom
{
    public class TimerTask : ThreadPool.TimerTask
    {

        /// <summary>
        /// 間隔 5000 毫秒執行一次
        /// </summary>
        public TimerTask()
            : base(餐廳.GetInstance.全局線程, 2000)
        {

        }

        public override void Run()
        {           
            IEnumerable<IScript餐桌檢查器> checkScripts = LoadScriptPool.LoadScriptManager.GetInstance.GetInstances<IScript餐桌檢查器>();
            foreach (var item in checkScripts)
            {
                item.Run();
            }
        }

    }
}

由於我們餐桌檢查器是一個不定數,所以需要放到腳本去。方便更新程序代碼。

在腳本項目裡面創建腳本文件

/**
 * 
 * @author 失足程序員
 * @Blog http://www.cnblogs.com/ty408/
 * @mail [email protected]
 * @phone 13882122019
 * 
 */
namespace Sz.Network.DiningRoom.Scripts
{
    public class Script餐桌檢查器 : IScript餐桌檢查器
    {

        Random random = new Random(DateTime.Now.Millisecond);

        public Script餐桌檢查器()
        {

        }

        public void Run()
        {
            Logger.Info("==================================Script餐桌檢查器=======================================");
            for (int i = 0; i < 餐廳.GetInstance.table.Length; i++)
            {
                if (餐廳.GetInstance.table[i] == null)
                {
                    int randomValue = random.Next(10000);
                    if (randomValue < 5000)
                    {
                        客人 客 = new 客人(i + 1);
                        餐廳.GetInstance.table[i] = 客;
                    }
                }
                else
                {
                    客人 客 = 餐廳.GetInstance.table[i];
                    if (客.Staus.HasFlag(客人.Status入座))
                    {
                        ///如果客人剛剛入座,執行點菜,移交給服務員
                        客.Staus |= 客人.Status點菜;
                        客.點菜();
                    }
                    else if (客.Staus.HasFlag(客人.Status等待就餐))
                    {
                        bool isFor = true;
                        foreach (var item in 客.菜肴s)
                        {
                            if (!item.Staus.HasFlag(菜肴.Status就餐))
                            {
                                isFor = false;
                                break;
                            }
                        }
                        if (isFor)
                        {
                            客.Staus |= 客人.Status就餐;
                            //模擬客人吃飯需要30到50秒
                            客.TempAttribute["Status就餐"] = SzExtensions.CurrentTimeMillis() + (random.Next(3, 6)) * 10 * 1000;
                        }
                        else
                        {
                            //模擬隨機事件
                            int randomValue = random.Next(10000);
                            if (randomValue < 6000)
                            {
                                Logger.Info("隨機事件發生 " + (i + 1) + " 號桌客人 添加茶水");
                                Task隨機事件發生處理器 task = new Task隨機事件發生處理器((i + 1) + " 號桌客人 添加茶水");
                                ThreadPool.ThreadManager.GetInstance.AddTask(餐廳.GetInstance.服務員s, task);
                            }
                        }
                    }
                    else if (客.Staus.HasFlag(客人.Status就餐))
                    {

                        if (客.TempAttribute.GetlongValue("Status就餐") < SzExtensions.CurrentTimeMillis())
                        {
                            客.Staus |= 客人.Status等待結賬;
                        }
                        else
                        {
                            //模擬隨機事件
                            string msg = "";
                            int randomValue = random.Next(10000);
                            if (randomValue < 3000)
                            {
                                msg = " 添加米飯";
                            }
                            else if (randomValue < 6000)
                            {
                                msg = " 添加茶水";
                            }

                            if (!string.IsNullOrWhiteSpace(msg))
                            {
                                Logger.Info("隨機事件發生 " + (i + 1) + " 號桌客人 " + msg);
                                Task隨機事件發生處理器 task = new Task隨機事件發生處理器((i + 1) + " 號桌客人 " + msg);
                                ThreadPool.ThreadManager.GetInstance.AddTask(餐廳.GetInstance.服務員s, task);
                            }
                        }
                    }
                    else if (客.Staus.HasFlag(客人.Status等待結賬))
                    {
                        客.Staus |= 客人.Status結賬中;
                    }
                    else if (客.Staus.HasFlag(客人.Status結賬中))
                    {
                        Logger.Info((i + 1) + " 號桌客人 結束就餐 送走客人");
                        餐廳.GetInstance.table[i] = null;
                        return;
                    }
                    客.Show();
                }
            }
        }
    }
}

點菜也同樣為方便程序更新,代碼放在腳本執行

/**
 * 
 * @author 失足程序員
 * @Blog http://www.cnblogs.com/ty408/
 * @mail [email protected]
 * @phone 13882122019
 * 
 */
namespace Sz.Network.DiningRoom.Scripts
{
    public class Script點菜 : IScript點菜
    {

        public Script點菜()
        {

        }

        public void Run(客人 客)
        {
            List<string> 菜肴_葷菜s = new List<string>() { "回鍋肉", "青椒肉絲", "東坡肘子", "糖醋排骨", "魚香肉絲" };
            List<string> 菜肴_素菜s = new List<string>() { "空心菜", "鳳尾", "素炒竹筍", "白油絲瓜" };
            List<string> 菜肴_湯s = new List<string>() { "番茄煎蛋湯", "紫菜蛋花湯", "酸菜粉絲湯", "素菜湯", "肉片湯" };
            Random random = new Random(DateTime.Now.Millisecond);
            {
                //int 數量 = random.Next(1, 菜肴_葷菜s.Count);
                int 數量 = 1;
                for (int i = 0; i < 數量; i++)
                {
                    int index = random.Next(菜肴_葷菜s.Count);
                    string name = 菜肴_葷菜s[index];
                    菜肴_葷菜s.RemoveAt(index);
                    菜肴 菜 = new 菜肴(name);
                    客.Add點菜(菜);
                }
            }
            {
                //int 數量 = random.Next(1, 菜肴_素菜s.Count);
                int 數量 = 1;
                for (int i = 0; i < 數量; i++)
                {
                    int index = random.Next(菜肴_素菜s.Count);
                    string name = 菜肴_素菜s[index];
                    菜肴_素菜s.RemoveAt(index);
                    菜肴 菜 = new 菜肴(name);
                    客.Add點菜(菜);
                }
            }
            {
                //int 數量 = random.Next(1, 菜肴_湯s.Count);
                int 數量 = 1;
                for (int i = 0; i < 數量; i++)
                {
                    int index = random.Next(菜肴_湯s.Count);
                    string name = 菜肴_湯s[index];
                    菜肴_湯s.RemoveAt(index);
                    菜肴 菜 = new 菜肴(name);
                    客.Add點菜(菜);
                }
            }
            客.Staus |= 客人.Status等待就餐;            
        }
    }
}

接下來,就是菜的流程任務執行器

/**
 * 
 * @author 失足程序員
 * @Blog http://www.cnblogs.com/ty408/
 * @mail [email protected]
 * @phone 13882122019
 * 
 */
namespace Sz.Network.DiningRoom
{
    public class Task菜 : ThreadPool.TaskModel
    {
        public 客人 客 { get; set; }

        public 菜肴 _菜肴 { get; set; }

        public Task菜(客人 客, 菜肴 _菜肴)
        {
            this.客 = 客;
            this._菜肴 = _菜肴;
        }

        public override void Run()
        {
            Random random = new Random(DateTime.Now.Millisecond);
            string 事件 = "";
            EnumStatus tempStatus = null;
            long threadID = 0;

            if (_菜肴.Staus.HasFlag(菜肴.Status點菜))
            {
                事件 = "洗菜";
                tempStatus = 菜肴.Status洗菜;
                threadID = 餐廳.GetInstance.洗菜員s;
            }
            else if (_菜肴.Staus.HasFlag(菜肴.Status取消))
            {
                事件 = "取消";
                tempStatus = 菜肴.Status取消;

            }
            else if (_菜肴.Staus.HasFlag(菜肴.Status洗菜))
            {
                事件 = "配菜";
                tempStatus = 菜肴.Status配菜;
                threadID = 餐廳.GetInstance.配菜員s;
            }
            else if (_菜肴.Staus.HasFlag(菜肴.Status配菜))
            {
                事件 = "炒菜";
                tempStatus = 菜肴.Status炒菜;
                threadID = 餐廳.GetInstance.廚師s;
            }
            else if (_菜肴.Staus.HasFlag(菜肴.Status炒菜))
            {
                事件 = "傳菜";
                tempStatus = 菜肴.Status傳菜;
                threadID = 餐廳.GetInstance.傳菜員s;
            }
            else
            {
                return;
            }

            int timer = random.Next(2000, 5000);
            ///模擬耗時
            Thread.Sleep(timer);

            ///修改菜肴的狀態
            this._菜肴.Staus |= tempStatus;

            Logger.Info(Thread.CurrentThread.Name + "  " + 客.TableID + " 號桌 客人 " + this._菜肴.Name +" "+ 事件 + " 耗時:" + timer);

            if (this._菜肴.Staus.HasFlag(菜肴.Status傳菜))
            {
                ///修改菜肴的狀態
                this._菜肴.Staus |= 菜肴.Status就餐;
            }

            if (threadID > 0)
            {
                //移交到下一個工作人員(線程)
                ThreadPool.ThreadManager.GetInstance.AddTask(threadID, this);
            }

        }

    }
}

我們修改一下餐廳的 init 方法

 //加載腳本
            LoadScriptPool.LoadScriptManager.GetInstance.LoadCSharpFile(new string[] { @"..\..\..\Sz.Network.DiningRoom.Scripts\" });
            //初始化定時器任務
            ThreadPool.ThreadManager.GetInstance.AddTimerTask(new TimerTask());

 

菜肴的流程,交給了 Task菜 類處理,菜肴的狀態值修改也是要交給 Task菜 修改的,保證了在同一線程修改狀態值就保證狀態值的正常。

既然說了要有隨機事件發生,那肯定少不了隨機事件的處理器

/**
 * 
 * @author 失足程序員
 * @Blog http://www.cnblogs.com/ty408/
 * @mail [email protected]
 * @phone 13882122019
 * 
 */
namespace Sz.Network.DiningRoom
{
    public class Task隨機事件發生處理器 : ThreadPool.TaskModel
    {

        string msg;
        public Task隨機事件發生處理器(string msg)
        {
            this.msg = msg;
        }

        public override void Run()
        {
            Random random = new Random(DateTime.Now.Millisecond);
            int timer = random.Next(2000, 5000);
            //模擬隨機事件耗時
            Thread.Sleep(timer);
            Logger.Info(Thread.CurrentThread.Name + " 處理隨機事件發生 " + msg + " 耗時:" + timer);
        }
    }
}

 

這樣我們就能啟動程序了測試一下了。

 

整個流程就是,客人入座,點菜,,被分配到到洗菜,配菜,炒菜,傳菜。就餐。結賬。等一系列流程。

由於人員配置不同,具體工作耗時不同,所以一切都發生都是不定項;

每一個操作在移交給下一個工作者(線程)都是不定操作。而每一個工作者(線程)都有先來後到的原則進行自己工作的處理;

 

我們未來方便測試和看清楚執行流程。我們只開啟一個餐桌;

 餐廳.GetInstance.Init(1);

 

我的程序真的能做飯哦~!

 

不知道,這樣講,是否能幫你講明白呢???

老規矩,全套源碼奉獻 svn 地址    http://code.taobao.org/svn/flynetwork_csharp/trunk/Flynetwork/BlogTest

跪求保留

/**
 * 
 * @author 失足程序員
 * @Blog http://www.cnblogs.com/ty408/
 * @mail [email protected]
 * @phone 13882122019
 * 
 */

 

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved