Java基础-红包雨游戏-多线程

发布于:2025-08-11 ⋅ 阅读:(15) ⋅ 点赞:(0)

目录

案例要求:

实现思路:

代码:

Employee

RedPacket

RedPacketRain

总结:


案例要求:

实现思路:

创建一个员工类,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保证线程安全,随机分配红包给员工。最终按员工抢到的总金额降序输出结果。关键点包括:使用同步锁保证金额累加安全,随机红包分配策略,以及线程间的并发控制。


网站公告

今日签到

点亮在社区的每一天
去签到