Java实现抢红包功能
采用多线程模拟多人同时抢红包。服务端将玩家发出的红包保存在一个队列里,然后用Job定时将红包信息推送给玩家。每一批玩家的抢红包请求,其实操作的都是从队列中弹出的第一个红包元素,但当前的红包数量为空的时候,自动弹出下一个红包(如果有的话)。
关键思想:
1.抢红包涉及多人并发操作,需要做好同步保证多线程运行结果正确。
2.由于同时在线人数大,从性能方面考虑,玩家的发红包请求不必及时响应,而由服务端定时执行发红包队列。
下面是主要的代码和实现逻辑说明
1.创建一个类,表示红包这个实体概念。直接采用原子变量保证增减同步。Java的原子变量是一种精度更细的同步机制,在高度竞争的情况下,锁的性能将超过原子变量的性能,但在更真实的竞争情况,原子变量享有更好的性能。
public class SpringGift {
private String role;
private AtomicInteger gift;
public String getRole() {
return role;
}
public void setRole(String role) {
this.role = role;
}
public AtomicInteger getGift() {
return gift;
}
public void setGift(AtomicInteger gift) {
this.gift = gift;
}
public int getRemainCount(){
return this.gift.get();
}
}
2.采用多线程模拟多人同时抢红包。服务端将玩家发出的红包保存在一个队列里,然后用Job定时将红包信息推送给玩家。每一批玩家的抢红包请求,其实操作的都是从队列中弹出的第一个红包元素,但当前的红包数量为空的时候,自动弹出下一个红包(如果有的话)。
public class Test {
public static ConcurrentLinkedQueue<SpringGift> queue;
public static SpringGift currGift;
public static AtomicInteger count = new AtomicInteger();
static class myThread implements Runnable{
public void run(){
handleEvent();
}
}
public static void main(String[] args) throws Exception {
queue = new ConcurrentLinkedQueue<SpringGift>();
for(int i =0;i<3;i++){
SpringGift gift = new SpringGift();
gift.setRole("role"+i);
gift.setGift(new AtomicInteger(50));
queue.add(gift);
}
myThread mythread = new myThread();
for(int i=0;i<1000;i++){
new Thread(mythread).start();
}
System.err.println("总共收到"+count.get());
}
private static SpringGift getGift(){
//防止多条线程同时弹出队首
synchronized (queue) {//若没有加锁,打印的count总数不对!!!!
if(currGift == null || currGift.getRemainCount() <=0){
currGift = queue.poll();
}
}
return currGift;
}
public static void handleEvent(){
try{
SpringGift obj = getGift();
if(obj == null || obj.getRemainCount() <= 0){
System.err.println("没有了");
return ;
}
if(obj !=null && obj.getGift().getAndDecrement() >0 ){
System.err.println("抢到一个红包");
count.getAndIncrement();
}
Thread.sleep(500);//模拟处理其他操作
}catch(Exception e){
e.printStackTrace();
}
}
}
运行结果部分截图如下

需要注意的是,getGift()这个方法,由于是自动弹出队首元素,必须做好同步机制,否则,当多个请求同时操作某一个红包的最后一次剩余时,会造成总的红包数量不正确。
(将加锁的代码注释后,会发现打印的总数量有可能不正确了!)
Java实现抢红包功能的更多相关文章
- 【Java EE 学习 21 下】【 使用易宝支付接口实现java网上支付功能】
一.网上支付分为两种情况,一种方法是使用直接和银行的支付接口,另外一种方法是使用第三方支付平台和银行对接完成支付. 1.直接和银行对接. 2.使用第三方支付平台 3.常见的第三方支付平台 二.使用易宝 ...
- 【Servlet】java web 文件下载功能实现
需求:实现一个具有文件下载功能的网页,主要下载压缩包和图片 两种实现方法: 一:通过超链接实现下载 在HTML网页中,通过超链接链接到要下载的文件的地址 <!DOCTYPE html> & ...
- Java 7 新增功能
Java 7 新增功能如下: 对二进制整数的支持,以0b或0B开头. 在数值中可以使用下划线,不管是整型数值,还是浮点型数值,都可以自由地使用下划线,这样可以直观地分辨数值常量中到底包含多少位.如:3 ...
- Java:延迟功能的Robot在Lunix系统上会报错
Java:延迟功能的Robot在Lunix系统上会报错 关于延迟功能的Robot: 今天开发过程中发现,本机开发好的项目,部署到Lunix服务器竟然报错!查了代码发现: Robot r = new R ...
- Atitit.java swing打印功能 api attilax总结
Atitit.java swing打印功能 api attilax总结 1. 打印方式有三种:2 1.1. 一是不经过任何修改,直接调用javascript中的window.print()打印.2 ...
- java实现验证码功能
java实现验证码功能 通过java代码实现验证码功能的一般思路: 一.通过java代码生成一张验证码的图片,将验证码的图片保存到项目中的指定文件中去,代码如下: package com.util; ...
- Java实现打印功能-AWT Graphics2D
Java实现打印功能 用java实现打印,java.awt中提供了一些打印的API,要实现打印,首先要获得打印对象,然后继承Printable实现接口方法print,以便打印机进行打印,最后用用Gra ...
- Java 14 新功能介绍
不做标题党,认认真真写个文章. 文章已经收录在 Github.com/niumoo/JavaNotes 和未读代码博客,点关注,不迷路. Java 14 早在 2019 年 9 月就已经发布,虽然不是 ...
- 超详细 Java 15 新功能介绍
点赞再看,动力无限.微信搜「程序猿阿朗 」,认认真真写文章. 本文 Github.com/niumoo/JavaNotes 和 未读代码博客 已经收录,有很多知识点和系列文章. Java 15 在 2 ...
随机推荐
- 区块链学习笔记:D02 区块链的技术发展历史和趋势
对于区块链的技术发展历史,其实在我的印象中也就对比特币有所了解,也听过什么火币之类的玩意,但是具体是什么.怎么运作的就不清楚了... 这次的内容首先是讲解了区块链的技术演进,一张图一目了然,虽然里面涉 ...
- Mysql的查询语句的使用
1. 简单查询 查询所有字段: SELECT * FROM 表名 查询特定字段: SELECT 字段列表 FROM 表名 2. 查询显示行号 - 在字段列表中加入(@rownum := @rownum ...
- luogu P2507 [SCOI2008]配对
题目描述 你有 n 个整数Ai和n 个整数Bi.你需要把它们配对,即每个Ai恰好对应一个Bp[i].要求所有配对的整数差的绝对值之和尽量小,但不允许两个相同的数配对.例如A={5,6,8},B={5, ...
- Java 将Excel转为PDF
本文将介绍在Java程序中如何将Excel工作簿转为PDF文档的,包括: 将整个工作簿转为PDF 将指定工作表转为PDF 使用工具:Free Spire.XLS for Java (免费版) Ja ...
- iOS开发-CoreMotion框架
转自: CoreMotion是一个专门处理Motion的框架,其中包含了两个部分 加速度计和陀螺仪,在iOS4之前加速度计是由 UIAccelerometer 类 来负责采集数据,现在一般都是用Cor ...
- hdu5969最大的位或
题目:http://acm.hdu.edu.cn/showproblem.php?pid=5969 题意:给定自然数l和r ,选取2个整数x,y,满足l <= x <= y <= r ...
- 【广州.NET社区推荐】【译】Visual Studio 2019 中 WPF & UWP 的 XAML 开发工具新特性
原文 | Dmitry 翻译 | 郑子铭 自Visual Studio 2019推出以来,我们为使用WPF或UWP桌面应用程序的XAML开发人员发布了许多新功能.在本周的 Visual Studio ...
- 基于cyusb3014的usb3.0双目摄像头开发测试小结(使用mt9m001c12stm)
测试图像 摄像头分辨率为1280*1024,双目分辨率为2560*1024 ps:时钟频率太高,时序约束还得进一步细化,图像偶尔会出现部分雪花,下一步完善
- Python发送邮件以及对其封装
对Python发送邮件进行封装 Python发送邮件分为四步 连接到smtp服务器 登陆smtp服务器 准备邮件 发送邮件 导入所需要的包 import smtplib from email.mime ...
- Day 03 Python 基础
目录 Pycharm 的使用 设置 快捷键 变量 什么是变量 定义变量 变量名的命名规则 变量名的两种命名方式 注释 快捷键(快速注释) 单行注释 多行注释 注释的作用 Turtle库的使用 Pych ...