目录
案例要求:
实现思路:
创建一个员工类,id和抢到的金额,创建一个红包类,里面就是金额,创建一个抽奖操作类,设置10个线程进行抢红包操作
代码:
Employee
import lombok.AllArgsConstructor;
public class Employee {
private final int id;
private int totalAmount; // 抢到的总金额
private final Object lock = new Object(); // 用于同步的锁对象
public Employee(int id) {
this.id = id;
this.totalAmount = 0;
}
// 线程安全的添加金额方法
public void addAmount(int amount) {
synchronized (lock) {
totalAmount += amount;
}
}
public int getId() {
return id;
}
public int getTotalAmount() {
synchronized (lock) {
return totalAmount;
}
}
}
RedPacket
public class RedPacket {
private final int amount; // 红包金额
public RedPacket(int amount) {
this.amount = amount;
}
public int getAmount() {
return amount;
}
}
RedPacketRain
import java.util.*;
import java.util.concurrent.CopyOnWriteArrayList;
public class RedPacketRain {
// 红包列表(使用线程安全的CopyOnWriteArrayList)
private static final List<RedPacket> redPackets = new CopyOnWriteArrayList<>();
// 员工列表
private static final List<Employee> employees = new ArrayList<>();
public static void main(String[] args) throws InterruptedException {
// 1. 初始化红包(200个)
generateRedPackets();
// 2. 初始化员工(100个)
for (int i = 1; i <= 100; i++) {
employees.add(new Employee(i));
}
// 3. 创建多个线程模拟抢红包
int threadCount = 10; // 10个抢红包线程
Thread[] threads = new Thread[threadCount];
for (int i = 0; i < threadCount; i++) {
threads[i] = new Thread(new GrabRedPacketTask(), "抢红包线程-" + (i + 1));
}
// 4. 启动所有线程
long startTime = System.currentTimeMillis();
for (Thread thread : threads) {
thread.start();
}
// 5. 等待所有线程执行完毕
for (Thread thread : threads) {
thread.join();
}
long endTime = System.currentTimeMillis();
System.out.println("\n===== 抢红包结束,耗时:" + (endTime - startTime) + "ms =====");
// 6. 按总金额排序并展示结果
employees.sort((e1, e2) -> Integer.compare(e2.getTotalAmount(), e1.getTotalAmount()));
System.out.println("\n===== 抢红包结果(按金额降序) =====");
for (Employee emp : employees) {
System.out.println("员工" + emp.getId() + ":总金额 " + emp.getTotalAmount() + "元");
}
}
// 生成红包(80%小红包1-30元,20%大红包31-100元)
private static void generateRedPackets() {
Random random = new Random();
// 160个小红包
for (int i = 0; i < 160; i++) {
redPackets.add(new RedPacket(random.nextInt(30) + 1));
}
// 40个大红包
for (int i = 0; i < 40; i++) {
redPackets.add(new RedPacket(random.nextInt(70) + 31));
}
}
// 抢红包任务
static class GrabRedPacketTask implements Runnable {
private final Random random = new Random();
@Override
public void run() {
// 循环抢红包,直到红包抢完
while (!redPackets.isEmpty()) {
// 随机获取一个红包(线程安全的移除)
RedPacket packet = null;
synchronized (redPackets) { // 保证红包列表操作的线程安全
if (!redPackets.isEmpty()) {
int index = random.nextInt(redPackets.size());
packet = redPackets.remove(index);
}
}
// 如果抢到红包,随机分配给一个员工
if (packet != null) {
int empIndex = random.nextInt(employees.size());
Employee emp = employees.get(empIndex);
emp.addAmount(packet.getAmount());
// 打印抢红包信息(可选,过多会影响性能)
// System.out.println(Thread.currentThread().getName() + ":员工" + emp.getId() + "抢到 " + packet.getAmount() + "元");
}
}
}
}
}
总结:
本文实现了一个多线程抢红包系统。系统包含三个核心类:Employee类(员工信息)、RedPacket类(红包金额)和RedPacketRain类(主程序)。通过10个线程模拟并发抢红包过程:初始化200个红包(80%为1-30元,20%为31-100元)和100个员工,使用CopyOnWriteArrayList保证线程安全,随机分配红包给员工。最终按员工抢到的总金额降序输出结果。关键点包括:使用同步锁保证金额累加安全,随机红包分配策略,以及线程间的并发控制。