目錄
案例要求:
實現思路:
代碼:
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();@Overridepublic 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保證線程安全,隨機分配紅包給員工。最終按員工搶到的總金額降序輸出結果。關鍵點包括:使用同步鎖保證金額累加安全,隨機紅包分配策略,以及線程間的并發控制。