C#多人抢票模拟器
火车票站点、订票、C#多人抢票模拟器【多线程】_ylq1045的专栏-CSDN博客
上次 抢票模拟器 假定高铁只有一个座位,现在设置高铁共有seatCount个座位
整体模拟程序如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace TrainPathBookingDemo
{
class Program
{
/// <summary>
/// 该高铁共有座位总个数
/// </summary>
static int seatCount = 3;
static void Main(string[] args)
{
LinkedList<string> stationList = new LinkedList<string>(new string[] { "A", "B", "C", "D", "E", "F", "G", "H", "I", "J", "K", "L", "M", "N" });
Console.WriteLine($"链表的首节点为【{stationList.First.Value}】");
Console.WriteLine($"链表的尾节点为【{stationList.Last.Value}】");
Tuple<string, string> route1 = Tuple.Create("C", "J");
Tuple<string, string> route2 = Tuple.Create("E", "M");
Console.WriteLine($"路线1【{route1.Item1}-->{route1.Item2}】 与 路线2【{route2.Item1}-->{route2.Item2}】是否相交:【{IntersectWith(stationList, route1, route2)}】");
route1 = Tuple.Create("B", "G");
route2 = Tuple.Create("G", "L");
Console.WriteLine($"路线1【{route1.Item1}-->{route1.Item2}】 与 路线2【{route2.Item1}-->{route2.Item2}】是否相交:【{IntersectWith(stationList, route1, route2)}】");
//四元组:第一项为订票人 第二项代表是否订票成功,第三项代表路线【起始站点】,第四项代表路线【终止站点】
List<Tuple<string, bool, string, string>> list = new List<Tuple<string, bool, string, string>>();
list.Add(Tuple.Create("甲", false, "A", "E"));
list.Add(Tuple.Create("乙", false, "B", "H"));
list.Add(Tuple.Create("丙", false, "E", "M"));
list.Add(Tuple.Create("丁", false, "K", "N"));
list.Add(Tuple.Create("戊", false, "C", "L"));
list.Add(Tuple.Create("己", false, "A", "N"));
list.Add(Tuple.Create("庚", false, "F", "J"));
list.Add(Tuple.Create("辛", false, "M", "N"));
list.Add(Tuple.Create("壬", false, "A", "F"));
list.Add(Tuple.Create("癸", false, "A", "G"));
Console.WriteLine($"------------下面模拟【{list.Count}】个人一起抢高铁票,假设本班高铁【链表】共有【{seatCount}】个座位了------------");
for (int i = 0; i < list.Count; i++)
{
int index = i;
Task.Run(() =>
{
FightTicket(stationList, list, list[index].Item1);
});
}
Console.ReadLine();
}
/// <summary>
/// 加锁
/// </summary>
static int lockedValue = 0;
/// <summary>
/// 抢票
/// </summary>
/// <param name="stationList">链表:高铁站点</param>
/// <param name="list">抢票人与路线 集合</param>
/// <param name="bookingPerson">当前抢票人</param>
static void FightTicket(LinkedList<string> stationList, List<Tuple<string, bool, string, string>> list, string bookingPerson)
{
//加锁
while (Interlocked.Exchange(ref lockedValue, 1) != 0)
{ }
Thread.Sleep(new Random((int)DateTime.Now.Ticks).Next(100, 500));
try
{
int index = list.FindIndex(tuple => tuple.Item1 == bookingPerson);
if (index == -1)
{
throw new Exception($"列表中不存在key,抢票人【{bookingPerson}】");
}
if (list[index].Item2)
{
//已经抢票成功,不能再次订票
Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")}【{bookingPerson}】-路线【{list[index].Item3}-->{list[index].Item4}】已订票,不能再次订票!");
return;
}
//查找出所有已经抢票成功的
List<Tuple<string, bool, string, string>> fightSuccessList = list.FindAll(tuple => tuple.Item2);
if (fightSuccessList.Count == 0)
{
//如果没有发现订票成功的,直接订票成功
list[index] = Tuple.Create(bookingPerson, true, list[index].Item3, list[index].Item4);
Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")}【{bookingPerson}】-路线【{list[index].Item3}-->{list[index].Item4}】已抢票成功");
return;
}
//存在已经抢票成功的,则检查所有路线是否存在相交冲突的
List<Tuple<string, bool, string, string>> tupleIntersect = fightSuccessList.FindAll(element =>
IntersectWith(stationList, Tuple.Create(element.Item3, element.Item4), Tuple.Create(list[index].Item3, list[index].Item4)));
if (tupleIntersect == null || tupleIntersect.Count == 0)
{
//如果没有发现路线相交的,订票成功
list[index] = Tuple.Create(bookingPerson, true, list[index].Item3, list[index].Item4);
Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")}【{bookingPerson}】-路线【{list[index].Item3}-->{list[index].Item4}】已抢票成功");
}
else
{
//斯内科 2022-03-06 增加余票个数查询逻辑
//发现存在路线相交的,则查询订票成功个数 是否大于等于 座位总个数,如果true【无剩余票】,则订票失败
if (tupleIntersect.Count >= seatCount)
{
Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")}【{bookingPerson}】订票失败,无余票!当前座位数【{seatCount}】,已抢票数【{tupleIntersect.Count}】,路线【{list[index].Item3}-->{list[index].Item4}】");
int bookingIndex = 0;
tupleIntersect.ForEach(tuple => Console.WriteLine($" 已订票人{++bookingIndex}:【{tuple.Item1}】路线【{tuple.Item3}-->{tuple.Item4}】"));
}
else
{
//如果有余票,则订票成功
list[index] = Tuple.Create(bookingPerson, true, list[index].Item3, list[index].Item4);
Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")}【{bookingPerson}】-路线【{list[index].Item3}-->{list[index].Item4}】已抢票成功,当前座位数【{seatCount}】,已抢票数【{tupleIntersect.Count + 1}】");
}
}
}
catch (Exception ex)
{
Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")}抢票时出现异常【{ex.Message}】,抢票人【{bookingPerson}】");
}
finally
{
//解锁
Interlocked.Exchange(ref lockedValue, 0);
}
}
/// <summary>
/// 指定的两条路线是否相交,元组的第一个元素代表起始站,第二个元素代表终点站
/// </summary>
/// <param name="stationList"></param>
/// <param name="route1">路线1</param>
/// <param name="route2">路线2</param>
/// <returns></returns>
static bool IntersectWith(LinkedList<string> stationList, Tuple<string, string> route1, Tuple<string, string> route2)
{
//元组的第一项代表起点,第二项代表终点
LinkedListNode<string> startNode1 = stationList.Find(route1.Item1);
LinkedListNode<string> endNode1 = stationList.Find(route1.Item2);
LinkedListNode<string> startNode2 = stationList.Find(route2.Item1);
LinkedListNode<string> endNode2 = stationList.Find(route2.Item2);
if (startNode1 == null || endNode1 == null || startNode2 == null || endNode2 == null)
{
//如果节点不存在,直接返回NG
return false;
}
if (startNode1.Value == startNode2.Value || endNode1.Value == endNode2.Value)
{
//如果是同一起始节点 或者 同一结束节点
return true;
}
bool existIntersect = false;
while (startNode1 != null)
{
startNode1 = startNode1.Next;
if (startNode1 != null && startNode1.Value == endNode1.Value)
{
//循环从开始节点到终止节点 结束
break;
}
if (startNode1 != null && (startNode1.Value == startNode2.Value || startNode1.Value == endNode2.Value))
{
//如果第二个起始节点在第一个元组的【From,To】之间 或者 第二个终点节点在第一个元组的【From,To】之间
existIntersect = true;
break;
}
}
if (existIntersect)
{
return true;
}
//查看 第一个起始节点在第二个元组的【From,To】之间 或者 第一个终点节点在第二个元组的【From,To】之间
while (startNode2 != null)
{
startNode2 = startNode2.Next;
if (startNode2 != null && startNode2.Value == endNode2.Value)
{
//循环从开始节点到终止节点 结束
break;
}
if (startNode2 != null && (startNode2.Value == startNode1.Value || startNode2.Value == endNode1.Value))
{
//如果第二个起始节点在第一个元组的【From,To】之间 或者 第二个终点节点在第一个元组的【From,To】之间
existIntersect = true;
break;
}
}
return existIntersect;
}
}
}
程序运行如图:
?
|