某一高铁,依次走过A->B->C->D->E->F->G->H->I->J->K->L->M->N 共十四个站点
我们可以使用链表来处理高铁的各个站点。
乘客甲乘车区间 A--->E
乘客乙乘车区间 B--->H
乘客丙乘车区间 E-->M
乘客丁乘车区间 K--->N
乘客戊乘车区间 C--->L
乘客己乘车区间 A-->N
乘客庚乘车区间 F--->J
乘客辛乘车区间 M--->N
假如这辆高铁只剩下一个座位了,多人进行抢票
多人抢票是否成功模拟器
乘车区间 ,即路线。
路线相交 则认为 某一人抢票成功后 ,第二人无法抢票
如果两条路线不相交,则相当于一个座位可以多次在不交叉的区间购票。
以下为多线程模拟多人同时抢票的C#程序。
源程序如下:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
namespace TrainPathBookingDemo
{
class Program
{
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"));
Console.WriteLine("------------下面模拟8个人一起抢高铁票,假设本班高铁【链表】只留下一个座位了------------");
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;
}
//存在已经抢票成功的,则检查所有路线是否存在相交冲突的
Tuple<string, bool, string, string> tupleIntersect = fightSuccessList.Find(element =>
IntersectWith(stationList, Tuple.Create(element.Item3, element.Item4), Tuple.Create(list[index].Item3, list[index].Item4)));
if (tupleIntersect == null)
{
//如果没有发现路线相交的,订票成功
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
{
//发现存在路线相交的,订票失败
Console.WriteLine($"{DateTime.Now.ToString("HH:mm:ss.fff")}【{bookingPerson}】订票失败!路线【{list[index].Item3}-->{list[index].Item4}】" +
$"与已订票人【{tupleIntersect.Item1}】路线【{tupleIntersect.Item3}-->{tupleIntersect.Item4}】存在冲突");
}
}
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;
}
}
}
模拟器运行如图: