多线程卖票深刻分析:为什么会出现只有一个窗口卖票的现象
一、需求分析:
模拟卖票窗口,实现5个窗口同时卖100张票(代码为了截图采用30张票)
知识点:多线程,锁,多线程的安全问题,线程的生命周期
二、代码实现
public class TestSellTickets {//此处也可采用普通的int//static int count = 30;static AtomicInteger count = new AtomicInteger(30);static String[] windows = {"窗口1","窗口2","窗口3","窗口4","窗口5"};public static void main(String[] args) {Thread[] threads = new Thread[5];Object o =new Object();for (int i=0;i<5;i++){threads[i] = new Thread(() -> { //采用lambda表达式创建线程,同时初始化给threads中的每个线程threads[i]while (true){if (count.get() >0){ //加锁前后双重判断,避免浪费锁资源synchronized (o){ //加锁,避免多个窗口同时卖一张票,实现线程安全if (count.get() >0) { //加锁前后双重判断,避免浪费锁资源try {Thread.sleep(100); //模拟卖票业务,停顿0.1秒} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + " 卖出第" + count + "张票");count.decrementAndGet();}else{System.out.println("余票不足停止售票~");break;}}}else{System.out.println("余票不足停止售票~");break;}}}, windows[i]);//windows[i]定义线程的名称}for (Thread thread:threads){thread.start(); //启动线程}}
}
代码中的关键部分已经注释
运行结果:
三、分析
通过以上代码,我们成功模拟了卖票问题,并且没有产生线程安全问题,
但是但是但是
为什么只要窗口1卖票,其他窗口并没有卖票,这样显然并不合理
原因:
捋一捋五个线程的生命周期,在上面的运行结果中,很明显是窗口1线start(),此时窗口1进入Runnable(可运行状态),尝试获取锁,发现并没有其他窗口持有锁,窗口1成功拿到锁并执行业务进行卖票;
而在窗口1之后启动的窗口2345在启动之后也尝试去获取锁,发现锁已经被别人拿走了,于是进入锁池,(注意:在同步状态下,没有获取到锁的会进入到等待队列中的锁池,锁池会比等待队列中的其他线程更优先于去获取锁);
在窗口1卖完1张票之后,开始释放锁,此时,窗口2345同时发现锁空了,正准备上去抢,结果窗口1发现自己又需要锁了,于是再次获取锁,窗口1一直围绕在锁的旁边,而窗口2345在锁池中的板凳上坐着,肯定没有窗口1抢的快。
四、解决
分析完问题的产生的原因之后,怎么解决呢,当然从源头下手,让窗口1在卖完一张票释放锁后晕眩(睡眠)10毫秒,让窗口2345启动冲刺去抢锁;
这里,我们采用了ReentrantLock锁(注意,最后一定要记得释放锁)
public class TestSellTickets2 {static int counts =100;static String[] windows={"窗口1","窗口2","窗口3","窗口4","窗口5"};public static void main(String[] args) {Lock lock = new ReentrantLock();Thread[] threads = new Thread[5];for (int i=0;i<5;i++){threads[i] = new Thread(() -> {while (true) {if (counts > 0) {lock.lock();try {if (counts > 0) {try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + "卖出第" + counts + "张票");counts--;} else {System.out.println(Thread.currentThread().getName() + "发现余票不足,停止售票");break;}}finally {lock.unlock(); //释放锁try {Thread.sleep(10); //晕眩10毫秒} catch (InterruptedException e) {e.printStackTrace();}}} else {System.out.println(Thread.currentThread().getName() + "发现余票不足,停止售票");break;}}},windows[i]);}for (Thread thread:threads){thread.start();}}
}
运行结果:
此时,发现5个窗口同时开始卖票,效率大大提高
欢迎评论区留下你的建议,大家一起讨论~~~
多线程卖票深刻分析:为什么会出现只有一个窗口卖票的现象相关推荐
- 想去看演唱却总是抢不到票?教你用Python制作一个自动抢票脚本
前言 嗨喽!大家好,这里是魔王!! 大麦网,是中国综合类现场娱乐票务营销平台,业务覆盖演唱会. 话剧.音乐剧.体育赛事等领域. 但是因为票数有限,还有黄牛们不能丢了饭碗,所以导致了,很多人都抢不到票 ...
- 周杰伦演唱会总是抢不到票?教你用Python做一个自动抢票脚本!
相信想去周董演唱会的大家都用过大麦网抢票吧? 可是 抢不到啊 该说不说 我抢到了 那么,今天带大家用Python来制作一个自动抢票的脚本小程序! 知识点: 面向对象编程 selenium 操作浏览器 ...
- 周杰伦演唱会总是抢不到票?教你用Python做一个自动抢票脚本
相信想去周董演唱会的大家都用过大麦网抢票吧? 可是 抢不到啊 该说不说 我抢到了 那么,今天带大家用Python来制作一个自动抢票的脚本小程序! 知识点: 面向对象编程 selenium 操作浏览器 ...
- 四窗口卖票 自己的票
四窗口卖票 自己的票 卖票线程 package demon四个窗口卖票;public class TicketSale extends Thread {public TicketSale(){}pub ...
- “票卡分析专用工具”功能介绍
"票卡分析专用工具"的由来 从一个萌动少年开始,来到北京,从此开始了北漂的生活...... 毕业工作虽然还没到八年,但有时候会回首想想一些工作方面的经历,总想 ...
- 多线程实现4个窗口卖100张票
技能点: 1.如何保证线程是多线程运行,而且不出现负票? 第一个while判断是外部判断,用于保持售票:而且在while循环中嵌入synchronized (){}是惯用方法,如果此处把while换为 ...
- java多线程同步 多窗口卖票实例_java多线程之火车售票系统模拟实例
1.前言 为了学习多线程共享与通信,我们模拟一个火车售票系统,假设有10张火车票,三个窗口(也就是三个线程)同时进行售票. 2.非同步代码 package com.tl.skyLine.thread; ...
- java 卖票问题_Java之多线程窗口卖票问题(Thread)
/** * * 例子:创建三个窗口卖票,总票数为100张.使用继承Thread类的方式 * * 存在线程的安全问题,待解决. * */ class Window extends Thread{ pri ...
- 程序模拟电影院窗口卖票,多线程Demo
某电影院目前正在上映国产大片,共有100张票,而它有3个窗口卖票,请设计一个程序模拟该电影院卖票 卖电影票Demo 实现步骤 1.SellTicket类 2.SellTicketDemo测试类 3.测 ...
最新文章
- Spring从菜鸟到高手(四)(上)使用JdbcTemplate类实现用户登陆验证、批量更新
- android程序贴吧,【Android 教程总结贴】归纳所有android贴
- 终于有人手把手用Java实现超市管理系统
- IC/FPGA 技术交流
- 3.7 测试时的 BatchNorm-深度学习第二课《改善深层神经网络》-Stanford吴恩达教授
- (视频+图文)机器学习入门系列-第3章 逻辑回归
- ActiveMQ的Transport Connectors配置(六)
- [Redux/Mobx] 在Redux中怎么发起网络请求?
- 数组名与指向数组的指针之间的联系与区别【数据结构】
- Hbase 实现微博好友关注功能
- 你不一定知道的vb6(2)
- 思科研究称80%的指纹认证机制均可遭绕过
- [POI2006]Tet-Tetris 3D
- node 版本管理器 之 nvm 安装与使用
- Vue+Webpack打造todo应用
- Linux学习--CentOS可视化配置网络
- 初识 Hbase 数据库
- java 如何保证配色通用_简单实用的通用配色法则,可以直接套用到日常的穿搭中...
- Dev-C++如何更改字体大小
- 一位研究生导师的肺腑之言