多线程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 = "";
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.同一个订单多个线程访问,一个个处理
2.多个订单多个线程,可以一起处理,完成的时间一样
3.同时运行
如有问题,请指出。
多线程demo,订单重复支付的更多相关文章
- 订单退款&重复支付需求疑问点归纳整理
更新历史记录: 更新内容 更新人 更新时间 新建 Young 2020.12.10 16:45 更新产品疑问解答 Young 2020.12.11 10:14 更新退款权益终止时间 Young 2 ...
- 黄聪:微信h5支付demo微信H5支付demo非微信浏览器支付demo微信wap支付
一.首先先确定H5支付权限已经申请! 二.开发流程 1.用户在商户侧完成下单,使用微信支付进行支付 2.由商户后台向微信支付发起下单请求(调用统一下单接口)注:交易类型trade_type=MWEB ...
- 微信支付id出现的重复支付解决方法和app应用中多种支付方式之间的对比
1.微信支付的transId发起支付请求,未登录微信,先帐号登陆,否则直接去支付.这样的话,该transId跟该帐号绑定起来了, 如果下一次再重新使用该transId来支付请求,但是想切换其他的微信帐 ...
- WEB安全新玩法 [8] 阻止订单重复提交
交易订单的重复提交虽然通常不会直接影响现金流和商品流,但依然会给网站运营方带来损害,如消耗系统资源.影响正常用户订单生成.制造恶意用户发起纠纷的机会等.倘若订单对象是虚拟商品,也有可能造成实际损失.订 ...
- Java 编程 订单、支付、退款、发货、退货等编号主动生成类
订单.支付.退款.发货.退货等编号主动生成类 在商城网站中,订单编号的自动生成,ERP中各个单据的编号自动生成,都可以按照一下的方式来自动生成. 第一步:定义常量订单编号前缀.订单编号起始数.订单编号 ...
- 苹果应用内购 ios 开发者根据用户提供的邮件中的订单号查看该订单是否支付成功
苹果应用内购 ios 开发者根据用户提供的邮件中的订单号查看该订单是否支付成功 这是苹果wwdc2021 推出的新功能 参考官网链接 App Store Server API | Apple Deve ...
- Java 实现订单未支付超时自动取消
在电商上购买商品后,如果在下单而又没有支付的情况下,一般提示30分钟完成支付,否则订单自动.比如在京东下单为完成支付: 超过24小时,就会自动取消订单,下面使用 Java 定时器实现超时取消订单功能. ...
- 微信支付之01------获取订单微信支付二维码的接口------Java实现
[ 前言:以前写过一个获取微信二维码支付的接口,发现最近公司新开的项目会经常用到,现在我又翻出代码看了一遍,觉得还是把整个代码流程记下来的好 ] 借鉴博客: 他这篇博客写得不错,挺全的:https:/ ...
- 微信h5支付demo微信H5支付demo非微信浏览器支付demo微信wap支付
服务项目 新手技术咨询 企业技术咨询 定制开发 服务说明 QQ有问必答 QQ.微信.电话 微信开发.php开发,网站开发,系统定制,小程序开发 价格说明 200元/月 1000/月 商议 ...
随机推荐
- 【LOJ】#2024. 「JLOI / SHOI2016」侦查守卫
题解 童年的回忆! 想当初,这是我考的第一次省选,我当时初二,我什么都不会,然后看着这个东西,是不是能用我一个月前才会的求lca,光这个lca我就调了一个多小时= =,然后整场五个小时,我觉得其他题不 ...
- 【POJ】3270.Cow Sorting
题解 用到一点群论的知识! 我们发现把操作写成一个置换后,一定是单个置换圈的内进行操作,把置换圈进行扩大的操作不优 我们有两个办法,一个是用全局最小的换进来,代替这个圈里最小的值,交换操作完成后再换出 ...
- nodejs 项目,请求返回Invalid Host header问题
今天在linux上安装node,使用node做一个web服务器,在linux上安装各种依赖以后开始运行但是,出现了:Invalid Host header 的样式,在浏览器调试中发现是node返回的错 ...
- docker 安装错误Transaction Check Error
安装docker提示:Transaction Check Error: file /usr/bin/docker from install of docker-io-1.7.1-2.el6.x86_6 ...
- 黑马程序员_java基础笔记(12)...内省(IntroSpector)
—————————— ASP.Net+Android+IOS开发..Net培训.期待与您交流!—————————— 1,了解JavaBean.2,BeanUtils工具包. 1,了解JavaBean. ...
- 8-1 binpacking uva1149(贪心)
题意:给定N个物品的重量Li 背包的容量M 同时要求每个背包最多装两个物品 求至少要多少个背包才能装下所有物品 简单贪心 注意输出: #include<bits/stdc++.h> u ...
- ecshop,大商创后台设置增加字段方法
使用场景:在开发过程中有时是需要在后台增加一个参数 例如: 必须要改数据库和源码的 1,在数据库中增加一条数据 数据库名称:shop_config 2:后台语言包
- 【知了堂学习笔记】java 编写几种常见排序算法2
排序的分类: 1.直接选择排序 它的基本思想是:第一次从R[0]~R[n-1]中选取最小值,与R[0]交换,第二次从R[1]~R[n-1]中选取最小值,与R[1]交换,....,第i次从R[i-1]~ ...
- 在静态方法中应用spring注入的类
最近在一次项目的重构中,原项目需要在静态方法中调用service,现在需要更换框架,service需要自动注入,无法再静态方法中调用 解决思路: 创建一个当前类的静态变量,创建一个方法,使用@Post ...
- Java I/O流输入输出,序列化,NIO,NIO.2
Java IO流 File类: File类是java.io包下代表和平台无关的文件和目录,File不能访问文件内容本身. File类基本操作: System.out.println("判断文 ...