多线程demo,订单重复支付

时间:2022-06-13 14:31:49

背景描述,一个商城网站,一个订单支付方案有多个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 = "";
const string secondOrderId = "";
const string thirdOrderId = "";
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, , lockType);
OrderPay(firstOrderId, , lockType);
OrderPay(firstOrderId, , lockType); Thread.Sleep(); Console.ForegroundColor = ConsoleColor.Yellow;
Console.WriteLine("----------------测试不同的订单-------------------");
Console.ForegroundColor = ConsoleColor.Green;
OrderPay(firstOrderId, , lockType);
OrderPay(secondOrderId, , lockType);
OrderPay(thirdOrderId, , lockType); } static void OrderPay(string orderId, int threadNo, LockType lockType)
{
new Thread(() => new Payment(orderId, threadNo).Pay(lockType)).Start();
Thread.Sleep();
}
} 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();
ShowMessage("完成操作,时间" + DateTime.Now);
}
private void ShowMessage(string message)
{
Console.WriteLine(string.Format("订单{0}的第{1}个线程{2}", LockString, ThreadNo, message));
}
}
public enum LockType
{
LockThis = ,
LockString = ,
LockObject = ,
LockStaticObject =
}
}
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, );
OrderPay(firstOrderId, );
OrderPay(firstOrderId, );
OrderPay(firstOrderId, );
//不同的订单可以同时处理
OrderPay(secondOrderId, );
OrderPay(thirdOrderId, );
OrderPay(fourthOrderId, );
OrderPay(fivthOrderId, );
}
/// <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[].ToString();
int ThreadNo = Convert.ToInt32(Params[]);
//加锁
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();
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.同一个订单多个线程访问,一个个处理

多线程demo,订单重复支付

多线程demo,订单重复支付

2.多个订单多个线程,可以一起处理,完成的时间一样

多线程demo,订单重复支付

3.同时运行

多线程demo,订单重复支付

如有问题,请指出。