ConcurrentLinkedQueue 模拟火车售票过程

Posted caoxb

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了ConcurrentLinkedQueue 模拟火车售票过程相关的知识,希望对你有一定的参考价值。

 

火车票类

 

public class Ticket {

    private String NO;    // 车票编号
    private double price; // 票价

    public Ticket(String nO, double price) {
        super();
        NO = nO;
        this.price = price;
    }

    public String getNO() {
        return NO;
    }

    public void setNO(String nO) {
        NO = nO;
    }

    public double getPrice() {
        return price;
    }

    public void setPrice(double price) {
        this.price = price;
    }

}

 

 

示例

public class TicketTest5 {
    
    private static Queue<Ticket> queue = new ConcurrentLinkedQueue<Ticket>();

    private static Map<String, String> log = new HashMap<>();    
    private static double totalMoney = 0;        // 总金额
    private static double initTotalMoney = 0;    // 初始化10000张票的总金额
    private static Object lock = new Object();
    
    /**
     * 初始化10000张火车票信息
     */
    static {
        
        for (int i=0; i<10000; i++) {
            double money = Math.ceil(Math.random() * 100);  // 随机金额
            initTotalMoney += money;               // 统计所有票的总金额
            Ticket ticket = new Ticket("NO_"+i, money);
            queue.add(ticket);
        }
        
    }
    
    /**
     * 模拟业务的付款操作
     */
    public static void pay(String no, double money) {
        try {
            Thread.sleep(10);
            synchronized (lock) {
                totalMoney += money;
                log.put(no, "出票日期:" + new Date());
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    
    public static void main(String[] args) {
        
        long start = System.currentTimeMillis();
        CountDownLatch latch = new CountDownLatch(1); // 用于最后打印信息
        // 启动100个窗口进行出票
        for (int i=0; i<100; i++) {
            Runnable run = new Runnable() {
                
                @Override
                public void run() {
                    // 每一个窗口出票数量不限,直至将所有的票售完
                    while (true) {
                        Ticket ticket = queue.poll();
                        if (ticket==null) {
                            latch.countDown();    // 打开门闩
                            break;
                        } else {
                            // 模拟付款
                            pay(ticket.getNO(), ticket.getPrice());
                            System.out.println("正在出票" + ticket.getNO());
                        }
                    }
                }
            };
            Thread thread = new Thread(run);
            thread.start();
        }
        // 暂停,直至所有的票都售完再执行下面操作
        try {
            latch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        long end = System.currentTimeMillis();
        // 将结果延时打印出来
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("耗时 :" + (end - start));
        System.out.println("10000张票初始总金额:" + initTotalMoney);
        System.out.println("售出总金额:" + totalMoney);
        System.out.println("合计售出数量 :" + log.size());
    }
}

 

输出结果:

 技术分享图片

 

以上是关于ConcurrentLinkedQueue 模拟火车售票过程的主要内容,如果未能解决你的问题,请参考以下文章

死磕 java集合之ConcurrentLinkedQueue源码分析

死磕 java集合之ConcurrentLinkedQueue源码分析

《人生重开模拟器》爆火出圈!我提前看遍人生无常……

Java并发容器--ConcurrentLinkedQueue

java LinkedBlockingQueue和ConcurrentLinkedQueue的区别

java并发之ConcurrentLinkedQueue