需求:
小明小红2人,分发礼物,礼物有好几类,总共有100个礼物,当发到少于10个时,不再发放,最后统计小明小红二人发放的数量。
思路:
(悲观锁)设置线程类GiftSender继承,重写run方法,同时定义数组里的礼物类型,随机数模拟100,然后加锁循环(我用的类.class;也可以专门上一个锁);然后计数统计,调get方法返回。
在主函数main方法里,再新建对象,启动,用join等执行完;再统计打印。
代码:
线程类GiftSender
import java.util.Random;
public class GiftSender implements Runnable {
private static final String[] GIFTS = {"玩具", "书籍", "文具", "零食", "衣服"};
private static int giftCount = 100; // 礼物总数
private static int xiaomingCount = 0; // 小明发放的礼物数量
private static int xiaohongCount = 0; // 小红发放的礼物数量
private final String senderName; // 发送者的名字
public GiftSender(String senderName) {
this.senderName = senderName;
}
@Override
public void run() {
Random random = new Random();
while (true) {
synchronized (GiftSender.class) {
if (giftCount < 10) {
break; // 礼物数量小于10时停止发放
}
giftCount--; // 减少礼物数量
String gift = GIFTS[random.nextInt(GIFTS.length)]; // 随机选择一个礼物
if (senderName.equals("小明")) {
xiaomingCount++;
} else {
xiaohongCount++;
}
System.out.println(senderName + " 发放了第 " + (100 - giftCount) + " 个礼物: " + gift);
}
try {
Thread.sleep(random.nextInt(100)); // 模拟发放礼物的时间
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static int getXiaomingCount() {
return xiaomingCount;
}
public static int getXiaohongCount() {
return xiaohongCount;
}
}
测试类Main类
public class Main {
public static void main(String[] args) {
// 创建两个线程,分别代表小明和小红
Thread xiaomingThread = new Thread(new GiftSender("小明"));
Thread xiaohongThread = new Thread(new GiftSender("小红"));
// 启动线程
xiaomingThread.start();
xiaohongThread.start();
// 等待线程结束
try {
xiaomingThread.join();
xiaohongThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 统计并打印结果
System.out.println("礼物发放结束。");
System.out.println("小明共发放了 " + GiftSender.getXiaomingCount() + " 个礼物。");
System.out.println("小红共发放了 " + GiftSender.getXiaohongCount() + " 个礼物。");
}
}
扩展:
乐观锁:AtomicInteger
的 compareAndSet
方法是乐观锁的核心,它会检查当前值是否与预期值一致,如果一致则更新,否则重试。使用AtomicInteger方法对数量进行判断。
扩展代码:
GiftSender类
import java.util.Random;
import java.util.concurrent.atomic.AtomicInteger;
public class GiftSender implements Runnable {
private static final String[] GIFTS = {"玩具", "书籍", "文具", "零食", "衣服"};
private static final AtomicInteger giftCount = new AtomicInteger(100); // 礼物总数,使用 AtomicInteger
private static final AtomicInteger xiaomingCount = new AtomicInteger(0); // 小明发放的礼物数量
private static final AtomicInteger xiaohongCount = new AtomicInteger(0); // 小红发放的礼物数量
private final String senderName; // 发送者的名字
public GiftSender(String senderName) {
this.senderName = senderName;
}
@Override
public void run() {
Random random = new Random();
while (true) {
int currentGiftCount = giftCount.get(); // 获取当前礼物数量
if (currentGiftCount < 10) {
break; // 礼物数量小于10时停止发放
}
// 尝试减少礼物数量(乐观锁的核心)
if (giftCount.compareAndSet(currentGiftCount, currentGiftCount - 1)) {
String gift = GIFTS[random.nextInt(GIFTS.length)]; // 随机选择一个礼物
if (senderName.equals("小明")) {
xiaomingCount.incrementAndGet(); // 增加小明发放的礼物数量
} else {
xiaohongCount.incrementAndGet(); // 增加小红发放的礼物数量
}
System.out.println(senderName + " 发放了第 " + (100 - currentGiftCount + 1) + " 个礼物: " + gift);
}
try {
Thread.sleep(random.nextInt(100)); // 模拟发放礼物的时间
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
public static int getXiaomingCount() {
return xiaomingCount.get();
}
public static int getXiaohongCount() {
return xiaohongCount.get();
}
}
Main类
public class Main {
public static void main(String[] args) {
// 创建两个线程,分别代表小明和小红
Thread xiaomingThread = new Thread(new GiftSender("小明"));
Thread xiaohongThread = new Thread(new GiftSender("小红"));
// 启动线程
xiaomingThread.start();
xiaohongThread.start();
// 等待线程结束
try {
xiaomingThread.join();
xiaohongThread.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
// 统计并打印结果
System.out.println("礼物发放结束。");
System.out.println("小明共发放了 " + GiftSender.getXiaomingCount() + " 个礼物。");
System.out.println("小红共发放了 " + GiftSender.getXiaohongCount() + " 个礼物。");
}
}