【业务分析
要完成抢红包的功能重点有两个:
- 多线程并发修改数据
- 红包现金分配算法
【类设计
用户对象:包含用户名称,所抢到的金额,最后的提示文言字段
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<Integer> moneys;
Moneys(List<Integer> 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<Integer> 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<User> 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<User> grabRedEnvelope(List<User> users,int money,int number) throws InterruptedException {
//预分配金额
Moneys moneys = getRandomMoney(number, money);
List<CompletableFuture> 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;
}
}
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。