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());
    }
}

输出结果:

原文地址:https://www.cnblogs.com/caoxb/p/9690993.html

时间: 2024-10-11 07:17:59

ConcurrentLinkedQueue 模拟火车售票过程的相关文章

编写三各类Ticket、SaleWindow、TicketSaleCenter分别代表票信息、售票窗口、售票中心。 售票中心分配一定数量的票,由若干个售票窗口进行出售,利用你所学的线程知识来模拟此售票过程。

package com.swift; import java.util.ArrayList; import java.util.HashMap; import java.util.List; import java.util.Map; public class TicketSaleCenter { public static void main(String[] args) { /* * 第6题: 编写三各类Ticket.SaleWindow.TicketSaleCenter分别代表票信息.售票

Mecanim Control试用——模拟前进加速过程

使用Mecanim动画系统有时会遇到大量转换连线导致状态图特别复杂杂乱.这时很多人希望能像旧的动画系统Animation那样用Play()函数来控制动画.Mecanim Control正式解决这问题的方案. 获取MecanimControl插件.官网购买地址https://www.assetstore.unity3d.com/en/#!/content/15156 新建Unity工程,导入MecanimControl.另下载并导入MecanimExampleScenes1.0作为动画测试资源.

使用httpClient模拟登陆开心网过程中登陆成功但是跳转不成功

package com.haojiahong.test; import java.util.ArrayList; import java.util.List; import org.apache.http.HttpResponse; import org.apache.http.NameValuePair; import org.apache.http.client.ResponseHandler; import org.apache.http.client.entity.UrlEncodedF

Servlet模拟网上售票问题,解决线程的安全问题

package com.lc.servlet; import java.io.IOException; import java.io.PrintWriter; import javax.servlet.ServletException; import javax.servlet.http.HttpServlet; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse;

Mysql模拟故障恢复案例过程

一.数据库全备,全备脚本如下: [[email protected] script]# cat bak_all.sh #!/bin/bash#Date: 2019-12-08#Author: chan#Mail: chan#Function:This scripts function is More complex backup scripts which need to find binlog log files and location points #Version: 1.1 USER=r

python模拟websocket握手过程中计算sec-websocket-accept

背景 以前,很多网站使用轮询实现推送技术.轮询是在特定的的时间间隔(比如1秒),由浏览器对服务器发出HTTP request,然后由服务器返回最新的数据给浏览器.轮询的缺点很明显,浏览器需要不断的向服务器发出请求,然而HTTP请求的header是非常长 的,而实际传输的数据可能很小,这就造成了带宽和服务器资源的浪费. Comet使用了AJAX改进了轮询,可以实现双向通信.但是Comet依然需要发出请求,而且在Comet中,普遍采用了长链接,这也会大量消耗服务器带宽和资源. 于是,WebSocke

【好记性不如烂笔头】约瑟夫环问题之形象解法(其实就是实实在在的模拟一下游戏过程)

1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Threading.Tasks; 6 7 namespace 约瑟夫环游戏 8 { 9 class Program 10 { 11 /* 12 * 约瑟夫环(约瑟夫问题)是一个数学的应用问题:已知n个人(以编号1,2,3...n分别表示)围坐在一张圆桌周围. 13 * 从编号为k的

Oracle11gr2_ADG管理之在备库上模拟failover的过程实战

技术建议和方案. 要求failover后不重建备库,并能够把failover的数据库重新切换回备库 主库为newtest,备库为snewtest 备库上已经开启了闪回 得到一个参考的SCN SQL> select current_scn from v$database; CURRENT_SCN ----------- 4491930 查看闪回数据库特性是打开的. SQL> select flashback_on from v$database; FLASHBACK_ON -----------

案例三:小明左右手分别拿两张纸牌:黑桃10和红心8,现在交换手中的牌。编写一个程序模拟这一个过程:两个整数分别保存在两个变量中,将这两个变量的值互换,并输出互换后的结果。

package project_03; /** * 2018-9-7 20:19:59 * @author Sauron XiaMen * */ public class ChangeCard { //将两个变量的值互换 public static void main(String[] args) { System.out.println("输出互换前手中的纸牌:"); int left=10; int right=8; int i=0; System.out.println(&quo