程序当然不能做饭。
之前的我们的系列文章,介绍, 多线程执行,任务派发。定时器执行。脚本加载。程序状态机。
这些都是零零散散,或者说都是模块化介绍,以及模块测试用例。
那么今天我们就来模拟正常程序流程。使用上述的功能性代码完成流程。
当然今天的测试用例程序肯定和做饭有关。今天要做的是模拟一个餐厅的流程。
完成 客人入座 -> 点菜 -> 等待就餐 -> 就餐 -> 等待结账 -> 结账 -> 离开.
期间包括 等待就餐 添加茶水,就餐的添加茶水,添加米饭等随机事件
新建控制台项目:
Sz.Network.DiningRoom 用于存放主文件项目
类库
Sz.Network.DiningRoom.Scripts 用于存放脚本文件项目
我们先来初始化餐厅。
/**
*
* @author 失足程序员
* @Blog http://www.cnblogs.com/ty408/
* @mail 492794628@qq.com
* @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) + " 号桌");
}
}
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
每一个工作人员都是一个线程。模拟线程。
我们这里,餐厅配置:"厨师", 3 "传菜员", 5 "服务员", 5 "配菜员", 3 "收银员", 1 "洗菜员", 2
各个环节的人员都不相同,且每一步操作都不进相同。
接下来我们初始化客人,
/**
*
* @author 失足程序员
* @Blog http://www.cnblogs.com/ty408/
* @mail 492794628@qq.com
* @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 + " 当前状态:" + 状态);
}
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
#p#
初始化菜肴
/**
*
* @author 失足程序员
* @Blog http://www.cnblogs.com/ty408/
* @mail 492794628@qq.com
* @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 + " 当前状态:" + 状态);
}
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
我们需要创建一个定时器任务,对餐桌和客人进行状态监测和随机事件发生器
/**
*
* @author 失足程序员
* @Blog http://www.cnblogs.com/ty408/
* @mail 492794628@qq.com
* @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();
}
}
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
由于我们餐桌检查器是一个不定数,所以需要放到脚本去。方便更新程序代码。
#p#
在脚本项目里面创建脚本文件
/**
*
* @author 失足程序员
* @Blog http://www.cnblogs.com/ty408/
* @mail 492794628@qq.com
* @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();
}
}
}
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
- 90.
- 91.
- 92.
- 93.
- 94.
- 95.
- 96.
- 97.
- 98.
- 99.
- 100.
- 101.
- 102.
- 103.
- 104.
- 105.
- 106.
- 107.
- 108.
- 109.
- 110.
- 111.
- 112.
- 113.
- 114.
- 115.
- 116.
- 117.
点菜也同样为方便程序更新,代码放在脚本执行
/**
*
* @author 失足程序员
* @Blog http://www.cnblogs.com/ty408/
* @mail 492794628@qq.com
* @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等待就餐;
}
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
#p#
接下来,就是菜的流程任务执行器
/**
*
* @author 失足程序员
* @Blog http://www.cnblogs.com/ty408/
* @mail 492794628@qq.com
* @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);
}
}
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
- 30.
- 31.
- 32.
- 33.
- 34.
- 35.
- 36.
- 37.
- 38.
- 39.
- 40.
- 41.
- 42.
- 43.
- 44.
- 45.
- 46.
- 47.
- 48.
- 49.
- 50.
- 51.
- 52.
- 53.
- 54.
- 55.
- 56.
- 57.
- 58.
- 59.
- 60.
- 61.
- 62.
- 63.
- 64.
- 65.
- 66.
- 67.
- 68.
- 69.
- 70.
- 71.
- 72.
- 73.
- 74.
- 75.
- 76.
- 77.
- 78.
- 79.
- 80.
- 81.
- 82.
- 83.
- 84.
- 85.
- 86.
- 87.
- 88.
- 89.
我们修改一下餐厅的 init 方法
//加载脚本
LoadScriptPool.LoadScriptManager.GetInstance.LoadCSharpFile(new string[] { @"..\..\..\Sz.Network.DiningRoom.Scripts\" });
//初始化定时器任务
ThreadPool.ThreadManager.GetInstance.AddTimerTask(new TimerTask());
- 1.
- 2.
- 3.
- 4.
菜肴的流程,交给了 Task菜 类处理,菜肴的状态值修改也是要交给 Task菜 修改的,保证了在同一线程修改状态值就保证状态值的正常。
既然说了要有随机事件发生,那肯定少不了随机事件的处理器
/**
*
* @author 失足程序员
* @Blog http://www.cnblogs.com/ty408/
* @mail 492794628@qq.com
* @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);
}
}
}
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.
- 9.
- 10.
- 11.
- 12.
- 13.
- 14.
- 15.
- 16.
- 17.
- 18.
- 19.
- 20.
- 21.
- 22.
- 23.
- 24.
- 25.
- 26.
- 27.
- 28.
- 29.
这样我们就能启动程序了测试一下了。
整个流程就是,客人入座,点菜,,被分配到到洗菜,配菜,炒菜,传菜。就餐。结账。等一系列流程。
由于人员配置不同,具体工作耗时不同,所以一切都发生都是不定项;
每一个操作在移交给下一个工作者(线程)都是不定操作。而每一个工作者(线程)都有先来后到的原则进行自己工作的处理;
我们未来方便测试和看清楚执行流程。我们只开启一个餐桌;
我的程序真的能做饭哦~!
不知道,这样讲,是否能帮你讲明白呢???
老规矩,全套源码奉献 svn 地址 http://code.taobao.org/svn/flynetwork_csharp/trunk/Flynetwork/BlogTest
跪求保留
/**
*
* @author 失足程序员
* @Blog http://www.cnblogs.com/ty408/
* @mail 492794628@qq.com
* @phone 13882122019
*
*/
- 1.
- 2.
- 3.
- 4.
- 5.
- 6.
- 7.
- 8.