再来系统动手学习一下Java并发编程。
知识点:CountDownLatch的发令枪使用模式;红包均分,最后一个分不完的解决方法
抢红包的需求,每个红包均分,最后一个除外
1. 设置红包总额
2. 设置红包的个数
3. 模拟抢红包的人数 (细节:涉及余额分配 10元3个人抢,得把钱分完)
4. 抢红包,同一时间多个人可以同时开始 (细节:要保证同时开始)
package com.lvzb.concurrent;import lombok.extern.slf4j.Slf4j;
import org.junit.jupiter.api.Test;import java.util.Scanner;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;/*** 抢红包案例** @author: lvzb31988* @date: 2023/01/09 20:00*/
@Slf4j
public class GrabRedEnvelopeTest {public static void main(String[] args) throws InterruptedException {int totalAmount;int num;int peopleNum;CountDownLatch countDownLatch = new CountDownLatch(1);Scanner scanner = new Scanner(System.in);System.out.println("请输入红包金额:");totalAmount = scanner.nextInt();System.out.println("请输入拆分多少个红包:");num = scanner.nextInt();System.out.println("请输入多少个人抢:");peopleNum = scanner.nextInt();RedEnvelope redEnvelope = new RedEnvelope(totalAmount, num, countDownLatch);// for (int i = 1; i <= peopleNum; i++) {
// new Thread(redEnvelope, "第" + i + "个人").start();
// }
// countDownLatch.countDown();ExecutorService pool = Executors.newFixedThreadPool(peopleNum);for (int i = 1; i <= peopleNum; i++) {pool.execute(redEnvelope);}countDownLatch.countDown();// 不关闭池的话,程序不会结束pool.shutdown();}/*** 抢红包的需求,每个红包均分,最后一个除外* 1. 设置红包总额* 2. 设置红包的个数* 3. 模拟抢红包的人数 (细节:涉及余额分配 10元3个人抢,得把钱分完)* 4. 抢红包,同一时间多个人可以同时开始 (细节:要保证同时开始)*/public static class RedEnvelope implements Runnable {/*** 红包总额*/private int totalAmount;/*** 红包个数*/private int num;/*** 每个红包均分的 额度*/private int eachAmount;/*** 特殊处理最后一个红包的额度,防止分不完*/private int lastAmount;// countDownLatch 的发令枪模式private CountDownLatch countDownLatch;// 保证线程安全private Object lock = new Object();public RedEnvelope(int totalAmount, int num, CountDownLatch countDownLatch) {this.totalAmount = totalAmount;this.num = num;this.countDownLatch = countDownLatch;this.eachAmount = totalAmount / num;// 最后一个红包金额 = 总额 - (红包总数-1)* 每个红包的数this.lastAmount = totalAmount - (num - 1) * eachAmount;}@Overridepublic void run() {synchronized (lock) {try {countDownLatch.await();} catch (InterruptedException e) {// 如果当前线程异常,就可以通知线程应该中断了Thread.currentThread().interrupt();e.printStackTrace();}int currentAmount;if (num != 1) {currentAmount = eachAmount;} else {currentAmount = lastAmount;}if (num > 0) {num--;System.out.println(Thread.currentThread().getName() + ": hhhh 我抢到了" + currentAmount + "元...");} else {System.out.println(Thread.currentThread().getName() + ": 没有抢到,错过一个亿...");}}}}
}

