火车票站点、订票、C#多人抢票模拟器【多线程】

某一高铁,依次走过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;        
        }
    }
}

模拟器运行如图:

 

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

斯内科

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值