Java并发-多线程售票案例

news2024/11/24 17:00:47

1. 前言

本节内容主要是使用 Java 的使用 Condition 和 Lock 机制对多线程售票案例进行实现。售票案例多数情况下主要关注多线程如何安全的减少库存,也就是剩余的票数,当票数为 0 时,停止减少库存。

2. 售票机制模型

如下图所示,有两个售票窗口进行售票,有一个窗口处理退票,这既是现实生活中一个简单的售票机制。

场景设计

  • 创建一个工厂类 TicketCenter,该类包含两个方法,saleRollback 退票方法和 sale 售票方法;
  • 定义一个车票总数等于 10 ,为了方便观察结果,设置为 10。学习者也可自行选择数量;
  • 对于 saleRollback 方法,当发生退票时,通知售票窗口继续售卖车票;
  • 对 saleRollback 进行特别设置,每隔 5000 毫秒退回一张车票;
  • 对于 sale 方法,只要有车票就进行售卖。为了更便于观察结果,每卖出一张车票,sleep 2000 毫秒;
  • 创建一个测试类,main 函数中创建 2 个售票窗口和 1 个退票窗口,运行程序进行结果观察。
  • 修改 saleRollback 退票时间,每隔 25 秒退回一张车票;
  • 再次运行程序并观察结果。
public class DemoTest {
        public static void main(String[] args) {
            TicketCenter ticketCenter = new TicketCenter();
            new Thread(new saleRollback(ticketCenter),"退票窗口"). start();
            new Thread(new Consumer(ticketCenter),"1号售票窗口"). start();
            new Thread(new Consumer(ticketCenter),"2号售票窗口"). start();
        }
}

class TicketCenter {
    private int capacity = 10; // 根据需求:定义10涨车票
    private Lock lock = new ReentrantLock(false);
    private Condition saleLock = lock.newCondition();
    // 根据需求:saleRollback 方法创建,为退票使用
    public void saleRollback() {
        try {
            lock.lock();
            capacity++;
            System.out.println("线程("+Thread.currentThread().getName() + ")发生退票。" + "当前剩余票数"+capacity+"个");
            saleLock.signalAll(); //发生退票,通知售票窗口进行售票
        } finally {
            lock.unlock();
        }
    }

    // 根据需求:sale 方法创建
    public void sale() {
        try {
            lock.lock();
            while (capacity==0) { //没有票的情况下,停止售票
                try {
                    System.out.println("警告:线程("+Thread.currentThread().getName() + ")准备售票,但当前没有剩余车票");
                    saleLock.await(); //剩余票数为 0 ,无法售卖,进入 wait
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            capacity-- ; //如果有票,则售卖 -1
            System.out.println("线程("+Thread.currentThread().getName() + ")售出一张票。" + "当前剩余票数"+capacity+"个");
        } finally {
            lock.unlock();
        }
    }
}

class saleRollback implements Runnable {
    private TicketCenter TicketCenter; //关联工厂类,调用 saleRollback 方法
    public saleRollback(TicketCenter TicketCenter) {
        this.TicketCenter = TicketCenter;
    }
    public void run() {
        while (true) {
            try {
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            TicketCenter.saleRollback(); //根据需求 ,调用 TicketCenter 的 saleRollback 方法

        }
    }
}
class Consumer implements Runnable {
    private TicketCenter TicketCenter;
    public Consumer(TicketCenter TicketCenter) {
        this.TicketCenter = TicketCenter;
    }
    public void run() {
        while (true) {
            TicketCenter.sale(); //调用sale 方法
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

总结:售票机制与生产者 - 消费者模式存在着细微的区别,需要学习者通过代码的实现慢慢体会。由于售票方法只需要进入 await 状态,退票方法需要唤醒售票的 await 状态,因此只需要创建一个售票窗口的 Condition 对象

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/43217.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

简单聊聊什么是react-redux,它能解决哪些问题

或许 在大多数人眼中 redux是一个相对复查很多的知识点 但确实如果你熟悉了流程 其实也比较简单的 redux是一个数据管理方案 我们先来举个例子 目前我们知道 react中有两种组件数据通信的方式 分别是 props 父传子 定义事件 子传父 通过事件将自己的数据传给父级 那如果是兄弟…

论硬件开发过程中开发文档规范化的重要性

硬件开发的标准化是公司管理过程中的重要组成部分,它离不开硬件开发文档的规范化,很多公司并不了解开发文档的重要性,容易将其忽视。一个项目开发完成后,还有着漫长的生命周期、售后维护和更新迭代,总结出开发文档&…

APS排程软件与ERP、MES的集成方式

ERP通常是企业第一个引入的信息系统,主要处理财务、订单、物料、人力资源等企业运营的基本数据,但ERP不能解决生产现场的问题。而要实现制造过程的精益化,对生产中的每个环节全面优化和监管,还需要其它的信息系统帮助。 ERP&#…

内网渗透笔记

内网靶场搭建 国内的红日安全团队曾提供内网渗透实战靶场的下载(大小共 13 G),你可以从百度网盘上下载,如果自己从头搭建测试环境的话,配置流程相当麻烦。 百度网盘:https://pan.baidu.com/s/1nC6V8e_EuK…

Win10 桌面图标出现空文件夹的删除及桌面图标排列问题

今天电脑开机后,桌面平白无故出现了两个空白的文件夹,也没有名字,如下图所示。 右键该文件夹后有以下下拉选项。 点击删除后,在回收站里面也没有这两个文件夹,在桌面鼠标右键,然后点击刷新后,…

【JavaScript高级】06-JavaScript对象知识增强

JavaScript对象的知识增强对属性操作的控制Object.defineProperty属性描述符属性描述符分类数据属性描述符(理解)存取属性描述符(掌握)对属性操作的控制 在前面我们的属性都是直接定义在对象内部,或者直接添加到对象内…

【MyBatis源码分析】一.JDBC回顾

MyBatis源码分析 文章目录 MyBatis源码分析一、JDBC开发回顾使用JDBC连接数据库SPI与JDBCDirverManagerDataSourceORM框架版本:mybatis 3.5.x 一、JDBC开发回顾 Java DataBase Connectivity Java 数据库连接, Java语言操作数据库 JDBC本质:其实是官方(sun公司)定义的一套…

mac-m1-docker安装nacos异常

目录 0. 官方文档 1. 修改docker的配置文件 2. 下载nacos代码 3. Dockerfile文件内容替换 4. 创建nacos的docker镜像 5. 启动nacos服务 6. 操作完后,打开docker mac docker安装nacos异常 0. 官方文档 Nacos Docker 快速开始 ERROR org.springframework.b…

无线遥控方案无线收发 soc 芯片 CI2451CI2454

无线遥控器、无线键鼠、无线玩具、无线灯控、无线音频等应用在生活中随处可遇,无线遥控最早起源于 18 世纪末,如今随着应用市场的扩大,家家户户也都用起了无线产品,这也意味着给人们带来极大便利的同时,成本也能得到大…

Flink的状态一致性

一致性的划分 通常来说,状态一致性分为三个级别 at-most-once:至多一次,发生故障恢复后数据可能丢失at-least-once:至少一次,发生故障恢复后数据可能多算,绝对不会少算exactly-once:精确一次&…

用二叉树或栈求表达式的值--代码实现+算法分析

解决表达式求值问题有两种方法,一种是利用栈和后缀表达式求解,另一种是二叉树中序存储表达式。所以本文分为栈和二叉树两大部分带领读者求解表达式。 1. 利用栈解决表达式求值问题 所谓表达式,就是由变量、常量以及运算符组合而成的式子。其…

集群部署看过来,低代码@AWS智能集群的架构与搭建方案

亚马逊AWS是葡萄城的生态合作伙伴。为了帮助您充分利用AWS的托管服务快速构建起一套集群环境,彻底去掉“单一故障点”,实现最高的可用性,我们准备了**《低代码智能集群AWS的架构与搭建方案》**看完本文,带你掌握“基于nginx配置服…

Origin绘制多折线图

Origin的优势区间相对于python和R在于数据量大时处理方便 尤其是多维度、多线、多拟合 尝试复现上图 1.首先把20列数据复制过去 2.全选之后(ctrlA),然后点Plot——Line 3.随便选一根线,双击进入属性设置(Origin交互设…

计算机网络-传输层:TCP协议

目录 一、协议格式 二、协议特性 1.面向连接 1.1三次握手建立连接 1.2四次挥手断开连接 为什么握手是三次,挥手是四次? 三次握手失败后,两端如何处理? 一台主机上出现了大量CLOSE_WAIT状态连接的原因? TIME_W…

基于神经网络多项式插值的图像超分辨重构研究-附Matlab代码

⭕⭕ 目 录 ⭕⭕✳️ 一、引言✳️ 二、基于单帧图像的超分辨率重构技术✳️ 2.1 最近邻域插值法✳️ 2.2 双线性插值法✳️ 2.3 双三次插值法(Keys’插值)✳️ 三、神经网络插值原理✳️ 3.1 训练阶段:✳️ 3.2 测试阶段✳️ 四、实验验证✳️ 4.1 基于神经网络双线…

Hive、Impala、Hue集成LDAP

1.LDAP简介 轻型目录访问协议,是一个开放的,中立的,工业标准的应用协议,通过IP协议提供访问控制和维护分布式信息的目录信息。在hadoop生态圈中,LDAP主要是用来做账号管理的。 2.LDAP安装配置 2.1 安装LDAP&#xf…

基于PHP+MYSQL宠物领养系统的开发与设计

市面上的宠物之家网站大多只是给爱宠人士一个交流的平台,给爱宠人士一个学习宠物习性,宠物购买的一个集合性的平台。很少有宠物领养功能,然而现在社会上有着太多的流浪宠物需要得到人们的关爱,这是很多宠物之家网站没有做到的。宠物之家网站正是顺应了当下的宠物热潮,为广大消费…

LeetCode | 1851.包含每个查询的最小区间

LeetCode | 1851.包含每个查询的最小区间 给你一个二维整数数组 intervals ,其中 intervals[i] [lefti, righti] 表示第 i 个区间开始于 lefti 、结束于 righti(包含两侧取值,闭区间)。区间的 长度 定义为区间中包含的整数数目&…

基于java+ssm+shiro的出租房管理平台

✌博主介绍✌:一个致力于全战开发的代码热爱者 龙门客栈管理平台一、前言介绍:二、系统设计:2.1 系统整体架构:2.1.1 数据库表结构的介绍:2.1.2 系统功能设计:三、功能截图:3.1 登录注册:3.2 基…

使用react-grid-layout和echarts-for-react实现一个支持拖拽的自定义响应式dashboard页面

使用react-grid-layout和echarts-for-react实现一个支持拖拽的自定义响应式dashboard页面 需求概要 在前端工作中,我们会经常遇到自定义dashboard页这样的需求。然后我想做一个能够让用户可以在面板上自由的拖拽,固定(不允许拖拽&#xff0…