问题引入

我们在上一章,引入了线程的概念,小明看完后,茅塞顿开,作为动物园的经理,他想用这种方式来解决动物园买票游客排队长的现象,他决定先用程序模拟一下:
设计4个售票窗口,总计售票100张。
用多线程的程序设计并写出代码。

错误案例一

小明作为经理比较忙,把这件事情丢给了秘书小张,小张说:“经理交给我吧,这有啥难的”

public class SaleTickets {public static void main(String[] args) {Tickets t1 = new Tickets();Tickets t2 = new Tickets();Tickets t3 = new Tickets();Tickets t4 = new Tickets();t1.start();t2.start();t3.start();t4.start();}
}
class Tickets extends Thread{int ticketnum = 100;@Overridepublic void run() {// TODO Auto-generated method stubwhile(ticketnum!=0) {System.out.println(super.getName()+"卖出了一张票"+"还有"+(--ticketnum)+"张");}}
}

小张写完后,测试了一下,好家伙直接可以卖四百张票。这该如何是好,小张想了好久最后也没有办法给小明打了电话。

错误案例二

小明回来后,细看,找到了错误。原来是定义的票数并不是公共资源,小张等于让每个人都卖了100张票,于是他把代码改为了:

public class SaleTickets {public static void main(String[] args) {Tickets t1 = new Tickets();Tickets t2 = new Tickets();Tickets t3 = new Tickets();Tickets t4 = new Tickets();t1.start();t2.start();t3.start();t4.start();}
}
class Tickets extends Thread{static int ticketnum = 100;@Overridepublic void run() {// TODO Auto-generated method stubwhile(ticketnum!=0) {System.out.println(super.getName()+"卖出了一张票"+"还有"+(--ticketnum)+"张");}}
}

果然没有出现类似的错误,在小张的马屁声中,小明经理又写了一种方法:

public class ApiRunSale {public static void main(String[] args) {Tickets2 t = new Tickets2();Thread t1 = new Thread(t);Thread t2 = new Thread(t);Thread t3 = new Thread(t);Thread t4 = new Thread(t);t1.start();t2.start();t3.start();t4.start();}
}
class Tickets2 implements Runnable{public int num = 100;@Overridepublic void run() {// TODO Auto-generated method stubwhile (num!=0) {try {Thread.sleep(10);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(Thread.currentThread().getName()+"卖出第"+(num--)+"张票");}}
}

随后大手一挥,好的!就这么办,明天我们就这样开始卖票!
结果,第二天,门卫老大爷抓到了好多拿着相同票的游客,大爷很生气,游客很委屈。最后经过一系列的测试,发现原来是不同的售卖员卖了同一张票…
售卖员也很委屈,因为有时候游客催的急,没来得及去问别的售卖员开票没有就得开票了。

错误案例三

小明经理说,你们哪怕是真的急也应该等一等,看清楚再出票,这样才不会出问题。

public class SaleTickets {public static void main(String[] args) {Tickets t1 = new Tickets();Tickets t2 = new Tickets();Tickets t3 = new Tickets();Tickets t4 = new Tickets();t1.start();t2.start();t3.start();t4.start();}
}
class Tickets extends Thread{static int ticketnum = 100;@Overridepublic void run() {int i=0;// TODO Auto-generated method stubwhile(ticketnum!=0) {System.out.println(super.getName()+"卖出第"+ticketnum+"票"+"还有"+(--ticketnum)+"张");i++;try {super.sleep(10);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}System.out.println(i);}
}

事实上等了等以后问题更严重了,因为售票员操作机器的时候要等一会儿,这个时候另一个售票员就把属于这个游客的票给了另一个游客…

最后小明说,要不然就限定一下,为了保证你们可以同步进行,我们提前确定一下,同一时间只能有一个人可以去卖票,卖完之前不能有另一个人过来打扰。
这也就是synchronized的概念

public class ApiRunSale {public static void main(String[] args) {Tickets2 t = new Tickets2();Thread t1 = new Thread(t);Thread t2 = new Thread(t);Thread t3 = new Thread(t);Thread t4 = new Thread(t);t1.start();t2.start();t3.start();t4.start();//synchronized;}
}
class Tickets2 implements Runnable{public int num = 100;@Overridepublic synchronized void run() {// TODO Auto-generated method stubwhile (num!=0) {System.out.println(Thread.currentThread().getName()+"卖出第"+(num--)+"张票");}}
}

可是这种情况下…进去一个线程剩下的就进不去了,所以我们的用法应该是:

public class ApiRunSale {public static void main(String[] args) {Tickets2 t = new Tickets2();Thread t1 = new Thread(t);Thread t2 = new Thread(t);Thread t3 = new Thread(t);Thread t4 = new Thread(t);t1.start();t2.start();t3.start();t4.start();//synchronized;}
}
class Tickets2 implements Runnable{public int num = 80000;@Overridepublic void run() {// TODO Auto-generated method stubwhile (num!=0) {synchronized(Thread.currentThread()) {System.out.println(Thread.currentThread().getName()+"卖出第"+(num--)+"张票");}}}
}

终于,成功解决了问题。

问题总结

首先我们要了解同步锁的概念其次我们要知道我们的同步锁具体应该锁到哪里。

同步锁的概念

把有可能出现问题的代码包起来,一次只让一个线程执行。通过sychronized关键字实现同步。
当多个对象操作共享数据时,可以使用同步锁解决线程安全问题。

特点

1、 前提1,同步需要两个或者两个以上的线程。
2、 前提2,多个线程间必须使用同一个锁。
3、 同步的缺点是会降低程序的执行效率, 为了保证线程安全,必须牺牲性能。
4、 可以修饰方法称为同步方法,使用的锁对象是this。
5、 可以修饰代码块称为同步代码块,锁对象可以任意。

注意我们锁的地方必须要是合理合适的临界区,如果太大了导致只有一个线程能进去(也就是最后),锁太小了就没有什么用处了。

JAVA 多线程的售票案例详解和收获相关推荐

  1. Java多线程之线程池详解

    Java多线程之线程池详解 目录: 线程池使用及优势 线程池3个常用方式 线程池7大参数深入介绍 线程池底层工作原理 1. 线程池使用及优势 线程池做的工作主要是控制运行的线程的数量,处理过程中将任务 ...

  2. JAVA多线程Thread VS Runnable详解

    进程与线程 进程是程序在处理机中的一次运行.一个进程既包括其所要执行的指令,也包括了执行指令所需的系统资源,不同进程所占用的系统资源相对独立.所以进程是重量级的任务,它们之间的通信和转换都需要操作系统 ...

  3. 它来了,阿里架构师的“Java多线程+并发编程”知识点详解手册,限时分享

    自学Java的时候,多线程和并发这一块可以说是最难掌握的部分了,很多小伙伴表示需要一些易于学习和上手的资料. 所以今天这份「Java并发学习手册」就是一份集中学习多线程和并发的手册,PDF版,由Red ...

  4. Java移除出界敌机,java实现飞机大战案例详解

    前言 飞机大战是一个非常经典的案例,因为它包含了多种新手需要掌握的概念,是一个非常契合面向对象思想的入门练习案例 程序分析: 在此游戏中共有六个对象: 小敌机Airplane,大敌机BigAirpla ...

  5. Java多线程同步和异步详解

    1. 多线程并发时,多个线程同时请求同一资源,必然导致此资源的数据不安全. 2. 线程池 在WEB服务中,对于web服务器的响应速度必须尽可能的快,这就容不得在用户提交请求按钮后,再创建线程提供服务. ...

  6. 【java】java多线程及线程池详解

    目录 前言 线程是什么?多线程是什么? 多线程的作用和好处以及缺点 守护线程和用户线程 并发和并行的区别 一.线程的状态和常用方法 1.线程各种状态转化图 2.线程相关常用方法有 ① wait() ② ...

  7. Java 多线程同步和异步详解

    多线程并发时,多个线程同时请求同一个资源,必然导致此资源的数据不安全,A线程修改了B线 程的处理的数据,而B线程又修改了A线程处理的数理.显然这是由于全局资源造成的,有时为了解 决此问题,优先考虑使用 ...

  8. Java多线程中join方法详解

    join()方法用于让当前执行线程等待join线程执行结束.其实现原理是不停的检查join线程是否存活,如果join线程存活则让当前线程永远等待. join()方法部分实现细节 while(isAli ...

  9. java同步方法完成案例_Java同步代码块和同步方法原理与应用案例详解

    本文实例讲述了java同步代码块和同步方法.分享给大家供大家参考,具体如下: 一 点睛 所谓原子性WOmoad:一段代码要么执行,要么不执行,不存在执行一部分被中断的情况.言外之意是这段代码就像原子一 ...

  10. java 同步块原理_Java同步代码块和同步方法原理与应用案例详解

    Java同步代码块和同步方法原理与应用案例详解 发布于 2020-8-7| 复制链接 摘记: 本文实例讲述了Java同步代码块和同步方法.分享给大家供大家参考,具体如下:一 点睛所谓原子性:一段代码要 ...

最新文章

  1. 利用WiFi模块实现MicroPython远程开发
  2. linux中文件的编辑 写入 读取 光标的位置 以及相应的补充
  3. 2.1.2 进程的状态与转换
  4. mysql数据库运行远程用户访问不了_MySQL数据库远程访问权限如何打开(两种方法)...
  5. 计算机组成原理 外部设备分为,2017考研计算机组成原理第七章考点:外部设备...
  6. LCD RGB 控制技术 时钟篇(下)
  7. AngularJS 1.3 支持使用 $digest() 循环实现延迟
  8. jqgrid mvc_jqGrid,REST,AJAX和Spring MVC集成
  9. 【maven】The forked VM terminated without saying properly
  10. OpenCV-Python实战(14)——人脸检测详解(仅需6行代码学会4种人脸检测方法)
  11. 色散方程用matlab编译,急切求助用matlab曲线拟合色散方程 - 程序语言 - 小木虫 - 学术 科研 互动社区...
  12. nRF52840 dongle BLE sniffer
  13. 拉文大学计算机科学,美国研究生语言双录取,这些大学有你中意的吗?
  14. 雷军《小米创业思考》读书笔记
  15. 怎么看待“别人恐惧我贪婪,别人贪婪我恐惧 “这句话
  16. 利用Dism修复系统步骤,以及dism找不到源文件解决方案
  17. linux的normal模式,解决grub rescue问题时发现grub/目录下没有文件normal.mod怎么办?...
  18. 推荐一个轻松搞定数据加密解密神器!
  19. 计算机网络 :P2P文件分发
  20. Mandiant对APT1组织的***行动的情报分析报告

热门文章

  1. LLM - 大模型速递 Baichuan2 快速入门
  2. hibernate逆向工程
  3. Python自动化与PDF
  4. 如何利用新闻营销塑造企业文化?
  5. linux libssl.so.10,libssl.so.10缺失库文件的解决办法
  6. 上海市计算机一级基础知识,上海市计算机一级基础知识复习.ppt
  7. 日常软件And网页浏览
  8. 计算机扫盲教案,小学信息技术听课记录
  9. innovus:如何在init design之后新增参考库(lib/lef)
  10. 7大类主流的3D打印技术(转载)