package homework;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.;
import java.util.concurrent.;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.concurrent.locks.LockSupport;
import static homework.common.Global.*;
public class ShopClient {
private static final Logger LOGGER = LoggerFactory.getLogger(ShopClient.class);
private static final Random RANDOM = new Random();
// 商品存储
private static final Map<Integer, Good> GOODS_STORE = new ConcurrentHashMap<>();
// 用户集合
private static final Map<Integer, User> USER_MAP = new ConcurrentHashMap<>();
// 抢购线程池
private static final ExecutorService THREAD_POOL = new ThreadPoolExecutor(
CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE_TIME, TimeUnit.SECONDS, new ArrayBlockingQueue<>(THREAD_QUEUE_CAPACITY)
);
/***
* 抢购活动
* result[0] 返回商品种类数量
* result[1] 返回商品购买次数
* result[2] 返回商品减少数量
*/
public static List<Integer> snapUpActive() {
List<Integer> results = new ArrayList<>();
init();
// 计算原始的商品种类的数量
int goodTypeNum = getGoodsTypeNum();
LOGGER.info("抢购开始前,商品总数为{}", goodTypeNum);
// 商品种类数量
Integer goodsTypeCount = GOODS_STORE.size();
// 商品购买次数
AtomicInteger buyCount = new AtomicInteger(0);
// 商品减少数量
AtomicInteger reduceCount = new AtomicInteger(0);
try {
// 初始化商品信息
// 执行抢购活动
long l = System.currentTimeMillis();
for (int i = 0; i < 5000; i++) {
User user = USER_MAP.get(RANDOM.nextInt(USER_MAP.size()) + 1);
THREAD_POOL.submit(new StoreThread(user, buyCount, reduceCount));
}
THREAD_POOL.shutdown();
System.out.println(System.currentTimeMillis() - l);
goodsTypeCount = getGoodsTypeNum();
// 运行后数据校验
results.add(goodsTypeCount);
results.add(buyCount.get());
results.add(reduceCount.get());
LOGGER.info("总数统计{},{},{}", goodsTypeCount, buyCount.get(), reduceCount.get());
} catch (Exception e) {
e.printStackTrace();
System.err.println("抢购活动运行报错");
}
return results;
}
private static int getGoodsTypeNum() {
int goodTypeNum = 0;
Set<Map.Entry<Integer, Good>> entries = GOODS_STORE.entrySet();
for (Map.Entry<Integer, Good> entry : entries) {
goodTypeNum += entry.getValue().getGoodAmount().get();
}
return goodTypeNum;
}
public static void init() {
// 缓存商品信息
GOODS_STORE.put(1, new Good(1, "华为手机", new AtomicInteger(1200), 2));
GOODS_STORE.put(2, new Good(2, "耳机", new AtomicInteger(2000), 2));
GOODS_STORE.put(3, new Good(3, "iPhone 20 pro max", new AtomicInteger(1500), 5));
GOODS_STORE.put(4, new Good(4, "iPad", new AtomicInteger(1300), 1));
GOODS_STORE.put(5, new Good(5, "电竞椅", new AtomicInteger(1000), 8));
GOODS_STORE.put(6, new Good(6, "OPPO手机", new AtomicInteger(1100), 1));
GOODS_STORE.put(7, new Good(7, "红米手机", new AtomicInteger(2500), 5));
GOODS_STORE.put(8, new Good(8, "电吹风", new AtomicInteger(3000), 1));
GOODS_STORE.put(9, new Good(9, "餐巾纸", new AtomicInteger(2500), 5));
GOODS_STORE.put(10, new Good(10, "电动车", new AtomicInteger(5000), 2));
// 缓存用户信息
USER_MAP.put(1, new User(1, "zhangsan", new AtomicInteger(5000)));
USER_MAP.put(2, new User(2, "lisi", new AtomicInteger(5000)));
USER_MAP.put(3, new User(3, "wangwang", new AtomicInteger(5000)));
USER_MAP.put(4, new User(4, "hh", new AtomicInteger(5000)));
USER_MAP.put(5, new User(5, "xioami", new AtomicInteger(5000)));
}
/**
* 通过内部类StoreThread模拟抢购行为
*/
private static class StoreThread implements Runnable {
private final User user;
private final AtomicInteger buyCount;
private final AtomicInteger reduceCount;
public StoreThread(User user, AtomicInteger buyCount, AtomicInteger reduceCount) {
this.user = user;
this.buyCount = buyCount;
this.reduceCount = reduceCount;
}
@Override
public void run() {
// if (user.getUserPoints().get() <= 0) {
// LOGGER.warn("用户 {} 购买失败,积分不足,当前用户积分为{}", user.getUserName(), user.getUserPoints().get());
// return;
// }
// int productId = RANDOM.nextInt(GOODS_STORE.size()) + 1;
// Good product = GOODS_STORE.get(productId);
// synchronized (product) {
// if (user.getUserPoints().get() < product.getPoint()) {
// LOGGER.warn("用户 {} 购买 {} 失败,积分不足,当前用户积分为{}", user.getUserName(), product.getGoodInfo(), user.getUserPoints().get());
// } else if (product.getGoodAmount().get() <= 0) {
// LOGGER.warn("用户 {} 购买 {} 失败,库存不足,当前商品库存为{}", user.getUserName(), product.getGoodInfo(), product.getGoodAmount().get());
// } else {
// user.getUserPoints().getAndAdd(-product.getPoint());
// product.getGoodAmount().decrementAndGet();
// buyCount.incrementAndGet();
// reduceCount.incrementAndGet();
// LOGGER.info("用户 {} 成功购买了 {},当前积分{},当前库存{}", user.getUserName(), product.getGoodInfo(), user.getUserPoints(), product.getGoodAmount());
// }
// }
if (user.getUserPoints().get() <= 0) {
LOGGER.warn("用户 {} 购买失败,积分不足,当前用户积分为{}", user.getUserName(), user.getUserPoints().get());
return;
}
int productId = RANDOM.nextInt(GOODS_STORE.size()) + 1;
Good product = GOODS_STORE.get(productId);
// 尝试购买商品,直到成功或积分不足
while (true) {
int currentPoints = user.getUserPoints().get();
int currentAmount = product.getGoodAmount().get();
// 检查积分和库存是否足够
if (currentPoints < product.getPoint() || currentAmount <= 0) {
LOGGER.warn("用户 {} 购买 {} 失败,积分不足或库存不足", user.getUserName(), product.getGoodInfo());
break;
}
// 使用 compareAndSet 进行乐观锁操作
boolean pointsUpdated = user.getUserPoints().compareAndSet(currentPoints, currentPoints - product.getPoint());
boolean amountUpdated = product.getGoodAmount().compareAndSet(currentAmount, currentAmount - 1);
if (pointsUpdated && amountUpdated) {
buyCount.incrementAndGet();
reduceCount.incrementAndGet();
LOGGER.info("用户 {} 成功购买了 {},当前积分{},当前库存{}", user.getUserName(), product.getGoodInfo(), user.getUserPoints(), product.getGoodAmount());
break; // 购买成功,退出循环
}
}
}
//
}
public static void main(String[] args) {
List<Integer> results = snapUpActive();
System.out.println("商品种类数量: " + results.get(0));
System.out.println("商品购买次数: " + results.get(1));
System.out.println("商品减少数量: " + results.get(2));
}
}