背景描述,一个商城网站,一个订单支付方案有多个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,订单重复支付的更多相关文章

  1. 订单退款&重复支付需求疑问点归纳整理

    更新历史记录: 更新内容 更新人 更新时间 新建 Young 2020.12.10  16:45 更新产品疑问解答 Young 2020.12.11  10:14 更新退款权益终止时间 Young 2 ...

  2. 黄聪:微信h5支付demo微信H5支付demo非微信浏览器支付demo微信wap支付

    一.首先先确定H5支付权限已经申请! 二.开发流程 1.用户在商户侧完成下单,使用微信支付进行支付 2.由商户后台向微信支付发起下单请求(调用统一下单接口)注:交易类型trade_type=MWEB ...

  3. 微信支付id出现的重复支付解决方法和app应用中多种支付方式之间的对比

    1.微信支付的transId发起支付请求,未登录微信,先帐号登陆,否则直接去支付.这样的话,该transId跟该帐号绑定起来了, 如果下一次再重新使用该transId来支付请求,但是想切换其他的微信帐 ...

  4. WEB安全新玩法 [8] 阻止订单重复提交

    交易订单的重复提交虽然通常不会直接影响现金流和商品流,但依然会给网站运营方带来损害,如消耗系统资源.影响正常用户订单生成.制造恶意用户发起纠纷的机会等.倘若订单对象是虚拟商品,也有可能造成实际损失.订 ...

  5. Java 编程 订单、支付、退款、发货、退货等编号主动生成类

    订单.支付.退款.发货.退货等编号主动生成类 在商城网站中,订单编号的自动生成,ERP中各个单据的编号自动生成,都可以按照一下的方式来自动生成. 第一步:定义常量订单编号前缀.订单编号起始数.订单编号 ...

  6. 苹果应用内购 ios 开发者根据用户提供的邮件中的订单号查看该订单是否支付成功

    苹果应用内购 ios 开发者根据用户提供的邮件中的订单号查看该订单是否支付成功 这是苹果wwdc2021 推出的新功能 参考官网链接 App Store Server API | Apple Deve ...

  7. Java 实现订单未支付超时自动取消

    在电商上购买商品后,如果在下单而又没有支付的情况下,一般提示30分钟完成支付,否则订单自动.比如在京东下单为完成支付: 超过24小时,就会自动取消订单,下面使用 Java 定时器实现超时取消订单功能. ...

  8. 微信支付之01------获取订单微信支付二维码的接口------Java实现

    [ 前言:以前写过一个获取微信二维码支付的接口,发现最近公司新开的项目会经常用到,现在我又翻出代码看了一遍,觉得还是把整个代码流程记下来的好 ] 借鉴博客: 他这篇博客写得不错,挺全的:https:/ ...

  9. 微信h5支付demo微信H5支付demo非微信浏览器支付demo微信wap支付

    服务项目 新手技术咨询 企业技术咨询 定制开发 服务说明 QQ有问必答 QQ.微信.电话 微信开发.php开发,网站开发,系统定制,小程序开发 价格说明 200元/月 1000/月 商议       ...

随机推荐

  1. Asp.net Vnext 自定义日志

    概述 本文已经同步到<Asp.net Vnext 系列教程 >中] 可以通过自定义日志,把错误消息记录到数据库 实现 在启动文件Startup Configure方法中加入自定义的日志提供 ...

  2. cetos6配置用msmtp和mutt发邮件(阿里云)

    Linux下可以直接用mail命令发送邮件,但是发件人是user@servername,如果机器没有外网的dns,其他人就无法回复.此时,有一个可以使用网络免费邮箱服务的邮件发送程序就比较重要了.ms ...

  3. Linux 的软件安装目录

    Linux 的软件安装目录是也是有讲究的,理解这一点,在对系统管理是有益的 /usr:系统级的目录,可以理解为C:/Windows/,/usr/lib理解为C:/Windows/System32. / ...

  4. Java学习笔记之:Struts2.0 环境搭建

    一.介绍 Struts2是一个基于MVC设计模式的Web应用框架,它本质上相当于一个servlet,在MVC设计模式中,Struts2作为控制器(Controller)来建立模型与视图的数据交互. 二 ...

  5. 谷歌pagerank算法简介

    在这篇博客中我们讨论一下谷歌pagerank算法.这是参考的原博客连接:http://blog.jobbole.com/71431/ PageRank的Page可是认为是网页,表示网页排名,也可以认为 ...

  6. ref:LDAP入门

    ref:https://www.jianshu.com/p/7e4d99f6baaf LDAP入门 首先要先理解什么是LDAP,当时我看了很多解释,也是云里雾里,弄不清楚.在这里给大家稍微捋一捋. 首 ...

  7. mysql正则表达式,实现多个字段匹配多个like模糊查询

    现在有这么一个需求 一个questions表,字段有题目(TestSubject),选项(AnswerA,AnswerB,AnswerC,AnswerD,AnswerE) 要求字段不包含png,jpg ...

  8. eclipse文本编码格式修改为UTF-8

    1.windows->Preferences...打开"首选项"对话框,左侧导航树,导航到general->Workspace,右 侧Text file encodin ...

  9. SERVLET API中forward()与redirect()的区别?

    前者仅是容器中控制权的转向,在客户端浏览器地址栏中不会显示出转向后的地址:后者则是完全的跳转,浏览器将会得到跳转的地址,并重新发送请求链接.这样,从浏览器的地址栏中可以看到跳转后的链接地址.所以,前者 ...

  10. iOS Sprite Kit教程之使用帮助文档以及调试程序

    iOS Sprite Kit教程之使用帮助文档以及调试程序 IOS中使用帮助文档 在编写代码的时候,可能会遇到很多的方法.如果开发者对这些方法的功能,以及参数不是很了解,就可以使用帮助文档.那么帮助文 ...