首页 > 其他分享 >Go - 高并发抢到红包实现

Go - 高并发抢到红包实现

时间:2022-12-29 16:23:35浏览次数:34  
标签:红包 money list 并发 num Go id left

// utils.go
package main

import (
"fmt"
"math/rand"
"sync"
"time"
)

// 抢红包任务结构体
type task struct {
id uint32 // 表示红包id
callback chan uint // 表示返回的金额
}

const TaskNums = 5 // 并发任务数

func main() {
id, money, num := 88, 100, 10

// 发红包
SetRedPack(id, money, num)

// 构造抢红包任务通道
for i := 0; i < TaskNums; i++ {
TasksChan[i] = make(chan task)
}

// 开启goroutine监听任务通道
go GetPackageMoney(TasksChan)

var wg sync.WaitGroup
// 抢红包
for i := 0; i < num+5; i++ {
wg.Add(1)
go GetRedPack(id, &wg)
}
wg.Wait()
}

var (
// 记录红包已抢总金额
sum uint = 0
TasksChan = make([]chan task, TaskNums) // 任务通道
random_seed = rand.New(rand.NewSource(time.Now().UnixNano())) // 分配的随机数
// 使用并发安全字典表示红包集
// key: uint32 为红包id
// value: []uint 为红包内随机金额的列表
packageList = new(sync.Map)
mu sync.Mutex
)

// 发红包方法
func SetRedPack(id, money, num int) {
left_money, left_num := money, num
money_list := make([]uint, num)
for left_money > 0 {

if left_num == 1 {
money_list[num-1] = uint(left_money)
break
}

if left_num == left_money {
for i := 0; i < left_num; i++ {
money_list[i] = 1
}
break
}

rMoney := int(2 * float64(left_money) / float64(left_num))
// 保证分配金额>=1
rand_m := random_seed.Intn(rMoney) + 1
money_list[num-left_num] = uint(rand_m)
left_money -= rand_m
left_num--
}
packageList.Store(uint32(id), money_list)
}

// 监听任务通道方法
func GetPackageMoney(taskschan []chan task) {
for {
select {
case t := <-taskschan[0]:
GetMoney(t)
case t := <-taskschan[1]:
GetMoney(t)
case t := <-taskschan[2]:
GetMoney(t)
case t := <-taskschan[3]:
GetMoney(t)
case t := <-taskschan[4]:
GetMoney(t)
default:
continue
}
}
}

func GetMoney(t task) {
id := t.id
l_money_list, ok := packageList.Load(id)

if ok && l_money_list != nil {
list := l_money_list.([]uint)
r_index := random_seed.Intn(len(list))
money := list[r_index]

// 更新红包金额列表信息
if len(list) > 1 {

if r_index == 0 {
packageList.Store(id, list[1:])
} else if r_index == len(list)-1 {
packageList.Store(id, list[:1])
} else {
packageList.Store(id,
append(list[:r_index], list[r_index+1:]...))
}

} else {
packageList.Delete(id)
}

t.callback <- money
} else {
t.callback <- 0
}
}

func GetRedPack(id int, wg *sync.WaitGroup) {
defer wg.Done()

// 并发安全字典取 value
list1, ok := packageList.Load(uint32(id))
list := list1.([]uint)
// 没取到就代表红包不存在
if !ok || len(list) < 1 {
fmt.Printf("红包不存在,id=%d\n", id)
}
// 构造抢红包任务
callback := make(chan uint)
t := task{
id: uint32(id),
callback: callback,
}
TasksChan[sum%TaskNums] <- t
money := <-t.callback
if money <= 0 {
fmt.Printf("很遗憾,你没有抢到红包\n")
} else {
fmt.Printf("恭喜你抢到一个红包,金额为:%d\n", money)
mu.Lock()
defer mu.Unlock()
sum += money
}
}

标签:红包,money,list,并发,num,Go,id,left
From: https://www.cnblogs.com/minch/p/17012891.html

相关文章

  • Django开发必备的10个第三方库
    以下的这几个第三方库,常用于Django开发中1.django-import-export:导入导出数据2.django-filter:过滤数据使用3.django-restframework:restful-Api使用4.pymysql:......
  • 1.Django安装和运行
    一、安装DjangoDjango框架是用Python语言开发的,只需要执行命令pipinstalldjango验证:python-mdjango--version>4.1.4切换到项目文件下,执行命令djang......
  • Go并发
    packagemainimport("fmt""runtime""sync""time")varcintfunccounter()int{c++returnc}funcmain2(){a:=100......
  • Django简介以及基本使用
    目录Django简介以及基本使用一、django简介1.web框架的本质是什么?2.python主流web框架有那些?3.web框架的推导过程二、基本使用1.运行django注意事项2.下载Django的终端命......
  • SpringBoot+MongoDB实现一个物流订单系统
    码字不易,点赞收藏,养成习惯!原创作者公众号:​​bigsai​​​,回复bigsai领取5G的PDF学习资源!共同进步。更多精彩期待与您分享!项目收录在​​​github​​​的​​MongoDB案例......
  • django项目中使用swagger来实现接口文档自动生成
    一、Swagger一般我们在对接前后端的时候,都需要提供相应的接口文档。对于后端来说,编写接口文档即费时费力,还会经常因为没有及时更新,导致前端对接时出现实际接口与文档不一......
  • 狂神说Go语言—错误与异常
    什么是错误error什么是错误错误指的是可能出现问题的地方出现了问题。比如打开一个文件时失败,这种情况在人们的意料之中。和错误类似的还有一个异常,指的是不应该出现......
  • 获取USG防火墙的NAT记录并发邮件给相应人员提醒
    授权USGNAT配置的时候需要遵循NAT_张三_20221201_长期importparamikoimportsmtplibfromemail.mime.textimportMIMETextfromemail.headerimportHeaderimpor......
  • 线程并发编程之美
    多线程并发编程之美等待线程执行终止的join方法执行的代码publicclassMyThreadThree{publicstaticvoidmain(String[]args)throwsInterruptedException......
  • 结合商业项目深入理解Go知识点
    这篇文章比较硬核,爆肝5千字,把之前整理的知识点都串起来了。建议先收藏,慢慢看。前言上一篇文章#【GoWEB进阶实战】开源的电商前后台API系统很受大家欢迎,有好多小伙伴......