资讯专栏INFORMATION COLUMN

java并发编程学习18--最迷你的抢红包

caohaoyu / 2501人阅读

摘要:业务分析要完成抢红包的功能重点有两个多线程并发修改数据红包现金分配算法类设计用户对象包含用户名称,所抢到的金额,最后的提示文言字段抢红包的用户用户昵称用户抢到的金额用户获得系统提示文言并发访问的共享红包对象这个对象包含了预分配的所有小红包并

【业务分析

要完成抢红包的功能重点有两个:

多线程并发修改数据

红包现金分配算法

【类设计

用户对象:包含用户名称,所抢到的金额,最后的提示文言字段

package com.xz.core;

/**
 * 抢红包的用户
 * @author ibm
 */
public class User {

    /**
     * 用户昵称
     */
    private String name;
    /**
     * 用户抢到的金额
     */
    private int money;
    /**
     * 用户获得系统提示文言
     */
    private String info;

    public User(String name, int money, String info) {
        this.name = name;
        this.money = money;
        this.info = info;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public double getMoney() {
        return money;
    }

    public void setMoney(int money) {
        this.money = money;
    }

    public String getInfo() {
        return info;
    }

    public void setInfo(String info) {
        this.info = info;
    }

}

并发访问的共享红包对象:这个对象包含了预分配的所有小红包并提供并发控制,用户线程只能通过这个类获得红包

package com.xz.core;

import java.util.List;

public class Moneys {

    /**
     * 预分配的红包金额
     */
    List moneys;

    Moneys(List moneys){
        this.moneys = moneys;
    }

    /**
     * 获得红包,如果一个用户获得了红包,改红包将从红包集合中移除
     * @return 红包金额
     */
    public synchronized Integer getMoney(){
        if(moneys.size() <= 0){
            return 0;
        }
        int money = moneys.get(0);
        moneys.remove(0);
        return money;
    }
}

用户线程:

 class GrabRedEnvelopeThread implements Runnable{
        /**
         * 该线程持有的用户对象
         */
        private User user;
        /**
         * 所有线程共享的与分配金额
         */
        private Moneys moneys;

        GrabRedEnvelopeThread(User user,Moneys moneys){
            this.user = user;
            this.moneys = moneys;
        }

        @Override
        public void run() {
            try {
                int myMoney = moneys.getMoney();
                user.setMoney(myMoney);
                if(myMoney > 0){
                    user.setInfo(user.getName() + " 获得 " +myMoney);
                }else {
                    user.setInfo(user.getName() + " 没抢到");
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
    }

红包金额分配算法:相当简陋的实现:

/**
     * 获取随机的红包金额
     * @param number 红包数量
     * @param money 红包金额
     * @return 随机红包
     */
    private Moneys getRandomMoney(int number,int money){
        List moneys = new ArrayList<>();
        int averageMoney = money / number;
        for (int i = 0; i < number; i++) {
            if(i == (number - 1)){
                moneys.add(money - moneys.stream().mapToInt(m -> m.intValue()).sum());
            }else {
                moneys.add((int)(Math.random() * averageMoney +1));
            }
        }
        if(moneys.size() != number){
            System.out.println("nq");
        }
        return new Moneys(moneys);
    }

代码模拟器:用于测试的客户端

import java.util.*;
import java.util.concurrent.CompletableFuture;

/**
 * 抢红包模拟器
 * @author ibm
 */
@SuppressWarnings("all")
public class BusinessSimulator {

    /**
     * 用户群
     */
    private List users = Arrays.asList(new User("王一",0,""),
            new User("牛二",0,""),
            new User("张三",0,""),
            new User("李四",0,""),
            new User("吴五",0,""),
            new User("赵六",0,""),
            new User("枸七",0,""));
    /**
     * 发出的金额
     */
    private int money = 100;
    /**
     * 红包数量
     */
    private int number = 3;

    public static void main(String[] args) throws InterruptedException {
        BusinessSimulator simulator = new BusinessSimulator();
        simulator.grabRedEnvelope(simulator.users,simulator.money,simulator.number);
        simulator.users.forEach(u -> {
            System.out.println(u.getInfo());
        });
    }

    /**
     * 抢红包方法
     * @param users 用户群
     * @param money 发出的金额
     * @param number 红包数量
     * @return 用户抢到红包集合
     */
   private List grabRedEnvelope(List users,int money,int number) throws InterruptedException {

        //预分配金额
        Moneys moneys = getRandomMoney(number, money);
        List futures = new ArrayList<>();
        for (int index = 0; index < users.size(); index++) {
            Runnable run = new GrabRedEnvelopeThread(users.get(index),moneys);
            futures.add(CompletableFuture.runAsync(run));
        }
        CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])).join();
        return users;
    }     
}
【结果

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/68686.html

相关文章

  • 后台 - 收藏集 - 掘金

    摘要:探究系统登录验证码的实现后端掘金验证码生成类手把手教程后端博客系统第一章掘金转眼间时间就从月份到现在的十一月份了。提供了与标准不同的工作方式我的后端书架后端掘金我的后端书架月前本书架主要针对后端开发与架构。 Spring Boot干货系列总纲 | 掘金技术征文 - 掘金原本地址:Spring Boot干货系列总纲博客地址:http://tengj.top/ 前言 博主16年认识Spin...

    CrazyCodes 评论0 收藏0
  • 99%的人都不知道春节抢票背后云计算在加持

    摘要:春节抢票应该是每个在外游子的必修课,还有不足一个月就要过春节了,现在的你,是不是还奋战在抢票一线呢说到抢票,之所以现在大家能享受到流畅的移动互联网购票服务,其实背后都是云计算在加持,没想到吧,原来看似高深的云计算离我们如此之近。春节抢票应该是每个在外游子的必修课,还有不足一个月就要过春节了,现在的你,是不是还奋战在抢票一线呢?说到抢票,之所以现在大家能享受到流畅的移动互联网购票服务,其实背后...

    megatron 评论0 收藏0
  • 并发

    摘要:表示的是两个,当其中任意一个计算完并发编程之是线程安全并且高效的,在并发编程中经常可见它的使用,在开始分析它的高并发实现机制前,先讲讲废话,看看它是如何被引入的。电商秒杀和抢购,是两个比较典型的互联网高并发场景。 干货:深度剖析分布式搜索引擎设计 分布式,高可用,和机器学习一样,最近几年被提及得最多的名词,听名字多牛逼,来,我们一步一步来击破前两个名词,今天我们首先来说说分布式。 探究...

    supernavy 评论0 收藏0
  • 并发

    摘要:表示的是两个,当其中任意一个计算完并发编程之是线程安全并且高效的,在并发编程中经常可见它的使用,在开始分析它的高并发实现机制前,先讲讲废话,看看它是如何被引入的。电商秒杀和抢购,是两个比较典型的互联网高并发场景。 干货:深度剖析分布式搜索引擎设计 分布式,高可用,和机器学习一样,最近几年被提及得最多的名词,听名字多牛逼,来,我们一步一步来击破前两个名词,今天我们首先来说说分布式。 探究...

    ddongjian0000 评论0 收藏0
  • 并发

    摘要:表示的是两个,当其中任意一个计算完并发编程之是线程安全并且高效的,在并发编程中经常可见它的使用,在开始分析它的高并发实现机制前,先讲讲废话,看看它是如何被引入的。电商秒杀和抢购,是两个比较典型的互联网高并发场景。 干货:深度剖析分布式搜索引擎设计 分布式,高可用,和机器学习一样,最近几年被提及得最多的名词,听名字多牛逼,来,我们一步一步来击破前两个名词,今天我们首先来说说分布式。 探究...

    wangdai 评论0 收藏0

发表评论

0条评论

最新活动
阅读需要支付1元查看
<