• 多线程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.同时运行

    如有问题,请指出。

  • 相关阅读:
    Commons.net FTPClient 上传文件
    C盘空间不够,清除VS下的 Font Cache
    Redis 密码设置
    Window bat expdp 定时任务逻辑备份 定时删除N天前的旧文件
    Windows下修改Oracle默认的端口1521
    Intellij idea 乱码问题(英文操作系统)
    给VMware下的Linux扩展磁盘空间(以CentOS6.3为例)转
    TortoiseSVN and TortoiseGit 版本控制图标不见了
    R语言中字符串的拼接操作
    SparkR:数据科学家的新利器
  • 原文地址:https://www.cnblogs.com/Jolinson/p/5489805.html
Copyright © 2020-2023  润新知