本次案例:模拟并发抢票
情景:300用户争夺100张门票
import lombok.extern.slf4j.Slf4j;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
@Slf4j
public class ExerciseSellTicket {
private static Random random = new Random();
public static void main(String[] args) throws InterruptedException {
//票数
TicketWindow ticketWindow = new TicketWindow(100);
ExecutorService executorService = Executors.newCachedThreadPool();
List<Integer> sellCount = new CopyOnWriteArrayList<Integer>();
CountDownLatch countDownLatch = new CountDownLatch(300);
//模拟多线程争抢
for (int i = 0; i < 300; i++) {
executorService.submit(()->{
countDownLatch.countDown();
int sellTicket = ticketWindow.sellTicket(randomAmount());
sellCount.add(sellTicket);
});
}
//阻塞main线程
countDownLatch.await();
executorService.shutdownNow();
log.info("本次卖出 {} 张票",sellCount.stream().mapToInt(c->c).sum());
log.info("剩余 {} 张票",ticketWindow.getCount());
}
// 随机 1~3
public static int randomAmount() {
return random.nextInt(3) + 1;
}
}
//卖票窗口
class TicketWindow {
//共享资源,总票数
private int count;
public TicketWindow(Integer count) {
this.count = count;
}
public Integer getCount() {
return count;
}
public void setCount(Integer count) {
this.count = count;
}
//成员变量count是共享变量,
// 对于我们而言,只需要保证同一时刻,只有一个线程能拿到count的值,进行操作,==》就可以达到同步的效果。
public synchronized int sellTicket(int amount) {
if (this.count >= amount) {
this.count -= amount;
return amount;
} else {
return 0;
}
}
}