概述:火车票20张,三个窗口同时卖火车票

一.创建一个Runnable接口的实现类TicketSell,重写run()方法

public class TicketSell implements Runnable{private int count = 20;  //票数20张@Overridepublic void run() {Thread thread = Thread.currentThread();   //使用Thread的静态方法获取当前Thread对象while(true){if(count>0){try {    Thread.sleep(200);   //相当于该线程被挂起,200ms后就绪再去抢占CPU运行  } catch (InterruptedException e) {e.printStackTrace();}System.out.println(thread.getName()+"  "+(--count));}}}}
二.创建测试类,main方法中,创建三个Thread对象(三个窗口);
package com.blueSky.TicketDemo;public class TicketTest {public static void main(String[] args) {TicketSell ticketSell = new TicketSell();  //3个窗口同卖20张票,使用一个Runnable接口的实现类//第一个窗口Thread thread1 = new Thread(ticketSell);thread1.setName("1号窗口");thread1.start();//第二个窗口Thread thread2 = new Thread(ticketSell);thread2.setName("2号窗口");thread2.start();//第三个窗口Thread thread3 = new Thread(ticketSell);thread3.setName("3号窗口");thread3.start();}
}
三.运行main方法进行测试
四 测试结果
五 问题分析
出现负数的原因:

进入条件后发生冲突,共享数据
睡眠相当于该线程被挂起,暂停执行,

* 假设此时count=1,线程1抢到CPU执行, 进入条件体,线程1休息200ms,该线程未执行count-1操作,*    所以下一个线程(比如线程3)抢到CPU执行时,count仍为1,仍会进入条件体,然后执行语句,睡眠200ms,*    当线程2到时,若两个线程还在睡眠(即都未执行count-1操作),count仍为1,线程3执行条件体,睡眠200ms,*    若之后线程1,睡眠时间到,且抢到了CPU执行,那么count-1  此时count=0*      然后线程2,3睡眠时间到,线程3抢到了CPU执行,那么count-1 此时count=0-1=-1     * *      然后线程3抢到了CPU ,那么执行count-1 此时count=-1-1=-2
六 .问题解决

使用同步锁,

  1. 使用同步代码块
package com.blueSky.TicketDemo;public class TicketSell implements Runnable{private int count = 20;  //票数20张@Overridepublic void run() {Thread thread = Thread.currentThread();   //使用Thread的静态方法获取当前Thread对象while(true){synchronized (this) {   //同步锁,同步代码块要把共享变量包进去if(count>0){try {    Thread.sleep(200);   } catch (InterruptedException e) {e.printStackTrace();}System.out.println(thread.getName()+"  "+(--count));}}}}}

2 封装方法,方法上加synchronized修饰

package com.blueSky.TicketDemo;public class TicketSell implements Runnable{private int count = 20;  //票数20张@Overridepublic void run() {Thread thread = Thread.currentThread();   //使用Thread的静态方法获取当前Thread对象while(true){
//          synchronized (this) {ticketCount(thread);    //封装方法,方法上加synchronized进行修饰
//          }}}private synchronized void ticketCount(Thread thread) {  //方法上加synchronized进行修饰,该方法为同步方法,该方法同时只能有一个线程访问。if(count>0){try {    Thread.sleep(200);   } catch (InterruptedException e) {e.printStackTrace();}System.out.println(thread.getName()+"  "+(--count));}}}

七. 同步锁好坏
优点:线程安全
缺点:效率低 (就像开关门要消耗时间一样)

Java学习--多线程案例--模拟火车票销售(线程安全问题)相关推荐

  1. 【Java 并发编程】【05】线程安全问题与线程同步

    5. 线程安全问题与线程同步 多线程编程是有趣且复杂的事情,它常常容易突然出现"错误情况",这是由于系统的线程调度具有一定的随机性.即使程序在运行过程中偶尔会出现问题,那也是由于我 ...

  2. 关于java Servlet,Struts,springMVC 的线程安全问题

    2019独角兽企业重金招聘Python工程师标准>>> 现在主流的java的前端框架有:struts1,struts2,springmvc 还有最根本的servlet; 前些天一个朋 ...

  3. 什么是Java内存模型?为什么会引发线程安全问题?

    近日,有热心市民就 "Java内存模型 " 提出质疑: 线程是否会把所有需要操作的数据全加载到内存 ​根据<我是憨包>可以看出,当事人蛋蛋(化名)目前情绪稳定,并且似乎 ...

  4. Java学习小型案例实战模拟-------播放器管理实战----------Java学习总结

    播放器管理 因为在Java内容当中,我们并没有学习图形界面的内容,所以播放器管理的内容呢都是在控制台来实现的. 需求分析: 播放列表管理: 将歌曲添加到主播放列表(集合) 将歌曲添加到普通播放列表 通 ...

  5. JAVA学习笔记33——模拟实现HandSet+数据存储综合练习(javabean版+容器板)

    最近在看JAVA教学的视频,觉得老师讲的很好,同时借用源代码还有笔记来撰写本系列博客,记录自己的学习内容,同时也供看到的人学习. 本篇第一个内容是模拟实现HandSet,其实这个模拟和之前的相比简陋了 ...

  6. java ftpclient多线程_Spring Boot整合FTPClient线程池的实现示例

    最近在写一个FTP上传工具,用到了Apache的FTPClient,但是每个线程频繁的创建和销毁FTPClient对象对服务器的压力很大,因此,此处最好使用一个FTPClient连接池.仔细翻了一下A ...

  7. Java学习--多线程

    1.实现多线程 1.1简单了解多线程[理解] 是指从软件或者硬件上实现多个线程并发执行的技术. 具有多线程能力的计算机因有硬件支持而能够在同一时间执行多个线程,提升性能. 1.11多线程实现三种方式( ...

  8. Java基础学习总结(143)——SimpleDateFormat线程安全问题重现、原因分析及解决方案

    分享一个大神的人工智能教程.零基础!通俗易懂!风趣幽默!还带黄段子!希望你也加入到人工智能的队伍中来!点击浏览教程 一.SimpleDateFormat作用: 进行时间的格式化输出和解析(注意:Sim ...

  9. java 学习~多线程通信 使用共享变量 例子和解释

    多线程互相通信一般使用共享变量.. 完整验证代码: main 方法 public class Test5 {public static void main(String[] args) {Datax ...

  10. java 银行账户 透支,Java学习——银行账户模拟

    以下实例是一个银行账户的模拟,通过银行卡的号码完成识别,可以进行存钱和取钱的操作. InsufficientFundsException.java 文件代码: // 文件名InsufficientFu ...

最新文章

  1. Win10 无需安装虚拟机/双系统使用 linux
  2. C++和C#相互调用COM组件的方法简介
  3. android 设置view最大高度,android-在RecyclerView上设置最大高度
  4. mysql中如何把两个查询结果列数不同并成一张表_MySQL
  5. 如何进行需求结构化管理?
  6. Google:2-1 tfkeras简介
  7. 不被大神Hinton认同,否定现有同行成果,谷歌这篇烧脑研究最终拿下ICML2019最佳论文...
  8. VC预处理指令与宏定义的妙用
  9. matlab调用cuda,Matlab 调用CUDA的总结(Windows、Ubuntu)
  10. 黑客编程入门 之 网络编程入门
  11. Opencv 傅立叶变换 傅立叶逆变换
  12. 数据存储的未来,磁带是赢家?!
  13. 毛刺现象 java_记一次微服务耗时毛刺排查
  14. SES2000处理水深
  15. 【GamePlay】时空回溯效果
  16. JTopo添加动态连线
  17. github.com连接超时 ping不通
  18. 聊聊自学,让你事半功倍的学习网站和工具
  19. 织梦图集php,织梦怎么为新图集页面增加图片下载功能
  20. JAVA设计模式之责任链模式

热门文章

  1. 目标跟踪——Tracking without bells and whistles
  2. MC(移动立方体)算法
  3. 电源防反接和防倒灌 - 使用MOS 管和运放实现理想二极管
  4. 三取二计算机,三取二是什么意思
  5. 1.1 PMBOK指南的目的 -- 项目管理知识体系指南(PMBOK指南)(第五版)
  6. #467 – 使用UniformGrid 均分行和列(Use a UniformGrid for Evenly Spaced Rows and Columns)
  7. win7怎样更改桌面计算机图标,教您电脑如何更改桌面图标
  8. 解决Pycharm挂代理后依旧插件下载慢
  9. 安装jdk后输入Javac提示不是内部或外部命令或者不出现tom猫
  10. LOCK is not allowed in stored procedures