多線程demo


背景描述,一個商城網站,一個訂單支付方案有多個1.金額支付2.積分支付3.工資支付(分期和全額),所以一個訂單的方案可能有1;有1、2,或1、2、3

狀態,1.訂單狀態,2,支付狀態==>多方案的訂單有多個支付狀態。

問題發現,一個訂單多次支付!!!

於是分析,找解決方案。

1.DB 行鎖

2.多線程控制

多線程測試參考 鏈接

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleThread
{
    class Program
    {
        const string firstOrderId = "001";
        const string secondOrderId = "002";
        const string thirdOrderId = "003";
        static void Main(string[] args)
        {
            test(LockType.LockObject);
            test(LockType.LockStaticObject);
            test(LockType.LockString);
            test(LockType.LockThis);
        }
        static void test(LockType lockType)
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("----------------測試相同的訂單-------------------");
            Console.ForegroundColor = ConsoleColor.Green;
            OrderPay(firstOrderId, 1, lockType);
            OrderPay(firstOrderId, 2, lockType);
            OrderPay(firstOrderId, 3, lockType);

            Thread.Sleep(1000);

            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine("----------------測試不同的訂單-------------------");
            Console.ForegroundColor = ConsoleColor.Green;
            OrderPay(firstOrderId, 1, lockType);
            OrderPay(secondOrderId, 1, lockType);
            OrderPay(thirdOrderId, 1, lockType);

        }

        static void OrderPay(string orderId, int threadNo, LockType lockType)
        {
            new Thread(() => new Payment(orderId, threadNo).Pay(lockType)).Start();
            Thread.Sleep(100);
        }
    }

    public class Payment
    {
        private readonly string LockString;
        private readonly int ThreadNo;
        private readonly Object LockObj = new object();
        private static readonly Object StaticLockObj = new object();

        public Payment(string orderId, int threadNo)
        {
            this.LockString = orderId;
            this.ThreadNo = threadNo;
        }

        public void Pay(LockType lockType)
        {
            ShowMessage("等待資源");
            switch (lockType)
            {
                case LockType.LockThis:
                    lock (this)
                    {
                        ShowAction();
                    }
                    break;
                case LockType.LockString:
                    lock (LockString)
                    {
                        ShowAction();
                    }
                    break;
                case LockType.LockObject:
                    lock (LockObj)
                    {
                        ShowAction();
                    }
                    break;
                case LockType.LockStaticObject:
                    lock (StaticLockObj)
                    {
                        ShowAction();
                    }
                    break;
                default:
                    break;
            }
            ShowMessage("釋放資源");
        }
        private void ShowAction()
        {
            ShowMessage("進入鎖並開始操作");
            Thread.Sleep(1000);
            ShowMessage("完成操作,時間" + DateTime.Now);
        }
        private void ShowMessage(string message)
        {
            Console.WriteLine(string.Format("訂單{0}的第{1}個線程{2}", LockString, ThreadNo, message));
        }
    }
    public enum LockType
    {
        LockThis = 0,
        LockString = 1,
        LockObject = 2,
        LockStaticObject = 3
    }
}
View Code

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;

namespace ConsoleThread2
{
    class Program
    {
        /// <summary>
        /// 訂單號
        /// </summary>
        const string firstOrderId = "d001";
        const string secondOrderId = "d002";
        const string thirdOrderId = "d003";
        const string fourthOrderId = "d004";
        const string fivthOrderId = "d005";
        static void Main(string[] args)
        {
            Test();
        }
        static void Test()
        {
            ConsoleOut.WriteWhite("----------------測試-------------------");
            //相同的訂單 一個一個來
            OrderPay(firstOrderId, 1);
            OrderPay(firstOrderId, 2);
            OrderPay(firstOrderId, 3);
            OrderPay(firstOrderId, 4);
            //不同的訂單可以同時處理
            OrderPay(secondOrderId, 5);
            OrderPay(thirdOrderId, 6);
            OrderPay(fourthOrderId, 7);
            OrderPay(fivthOrderId, 8);
        }
        /// <summary>
        /// 多線程支付
        /// </summary>
        /// <param name="orderId">訂單號</param>
        /// <param name="threadNo">線程編號</param>
        static void OrderPay(string orderId, int threadNo)
        {
            new Thread((object x) => Payment.Pay(new object[] { orderId, threadNo })).Start();
        }
    }
    /// <summary>
    /// 鎖字典一個訂單對映一個鎖
    /// </summary>
    public static class DicLockManage
    {
        /// <summary>
        /// 根據訂單id得到,鎖資源
        /// </summary>
        public static Dictionary<string, object> dicLock = new Dictionary<string, object>();
        /// <summary>
        /// 字典操作的鎖
        /// </summary>
        public static readonly object objLock = new object();
        /// <summary>
        /// 得到訂單鎖
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        public static object GetKeyValue(string key)
        {
            lock (objLock)
            {
                if (dicLock.ContainsKey(key))
                {
                    return dicLock[key];
                }
                else
                {
                    dicLock.Add(key, new object());
                    return GetKeyValue(key);
                }
            }
        }
    }
    /// <summary>
    /// 訂單支付類
    /// </summary>
    public static class Payment
    {
        /// <summary>
        /// 模擬支付方法
        /// </summary>
        /// <param name="objParams"></param>
        public static void Pay(object[] objParams)
        {
            object[] Params = objParams as object[];
            string OrderId = Params[0].ToString();
            int ThreadNo = Convert.ToInt32(Params[1]);
            //加鎖
            lock (DicLockManage.GetKeyValue(OrderId))
            {
                ShowMessage(OrderId, ThreadNo, "等待資源");
                ShowAction(OrderId, ThreadNo);//模擬支付
                ShowMessage(OrderId, ThreadNo, "釋放鎖");
            }
        }
        private static void ShowAction(string OrderId, int ThreadNo)
        {
            ShowMessage(OrderId, ThreadNo, "進入鎖並開始操作");
            ConsoleOut.WriteRed("線程" + ThreadNo + "處理中...");
            Thread.Sleep(3000);
            ConsoleOut.WriteGreen("線程" + ThreadNo + "完成處理...");
            ShowMessage(OrderId, ThreadNo, "完成操作,時間" + DateTime.Now);
        }
        private static void ShowMessage(string OrderId, int ThreadNo, string message)
        {
            ConsoleOut.WriteYellow(string.Format("訂單{0}的第{1}個線程{2}", OrderId, ThreadNo, message));
        }
    }
    /// <summary>
    /// 輸出類,設置顏色
    /// </summary>
    public static class ConsoleOut
    {
        public static void WriteWhite(string message)
        {
            Console.ForegroundColor = ConsoleColor.White;
            Console.WriteLine(message);
        }
        public static void WriteRed(string message)
        {
            Console.ForegroundColor = ConsoleColor.Red;
            Console.WriteLine(message);
        }
        public static void WriteYellow(string message)
        {
            Console.ForegroundColor = ConsoleColor.Yellow;
            Console.WriteLine(message);
        }
        public static void WriteGreen(string message)
        {
            Console.ForegroundColor = ConsoleColor.Green;
            Console.WriteLine(message);
        }
    }
}

測試圖

1.同一個訂單多個線程訪問,一個個處理

2.多個訂單多個線程,可以一起處理,完成的時間一樣

3.同時運行

如有問題,請指出。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM