JAVA学习之路(多线程)---模拟售票(细解)
2018-12-27 07:42:49来源:博客园 阅读 ()
首先看题目描述:
假设有火车票100张,创建4个线程模拟4个售票点,每100ms售出一张,打印出售票过程,格式如下:
窗口3:卖出第100张票
窗口4:卖出第99张票
............
............
简单的思路就是创建一个类,首先肯定要去继承Thread。开启线程,由于是4个窗口,肯定要开启4个线程。然后让每个线程去输出结果,也就是卖出去的票。这里很多人想不到如何让4个线程不打印重复的票。(比如4个线程都卖出去了第100张票,这显然是不合理的)。
看代码:
1 package com.lesson.thread; 2 3 public class MyThread { 4 5 public static void main(String[] args) { 6 Ticket sell1 = new Ticket(); 7 Ticket sell2 = new Ticket(); 8 Ticket sell3 = new Ticket(); 9 Ticket sell4 = new Ticket(); 10 sell1.setName("窗口1"); 11 sell2.setName("窗口2"); 12 sell3.setName("窗口3"); 13 sell4.setName("窗口4"); 14 sell1.start(); 15 sell2.start(); 16 sell3.start(); 17 sell4.start(); 18 } 19 } 20 class Ticket extends Thread { 21 private static int tickets = 100;//这里设置成static,目的是让每个线程共享这个变量。以免出现重复打印的现象。 22 @Override 23 public void run() { 24 while(true) { 25 if(tickets <= 0) { 26 break; 27 } 2829 System.out.println(getName()+":买出第"+tickets--+"张票。");//卖出一张减一张票 30 31 } 32 } 33 34 }
可能你已经看到了你想要的结果了。但是,还没完。目前代码写到这里是有问题的!!!
为什么?
看下面的代码:
package thread; public class Mythread { public static void main(String[] args) { Ticket sell1 = new Ticket(); Ticket sell2 = new Ticket(); Ticket sell3 = new Ticket(); Ticket sell4 = new Ticket(); sell1.setName("窗口1"); sell2.setName("窗口2"); sell3.setName("窗口3"); sell4.setName("窗口4"); sell1.start(); sell2.start(); sell3.start(); sell4.start(); } } class Ticket extends Thread { private static int tickets = 100; @Override public void run() { while(true) { if(tickets <= 0) { break; } try { Thread.sleep(10); //让进来的线程睡10ms;线程1,2,3,4都睡在这 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(getName()+":买出了第"+tickets--+"张票。"); } } }
与开始的代码不同在于让进来的线程睡一会。可以看到如下运行结果:
窗口2:买出了第0张票。
窗口3:买出了第-1张票。
窗口1:买出了第-2张票。
这里编者调出来了出问题的地方。可以看到怎么会第0,-1,-2张票???
做出解释:
其实在这里让线程睡一会就是为了演示这里有很多行代码要执行。假设票已经卖到第1张了,也就是tickets=1,然后第一条线程进来判断 tickets <= 0 ?不成立,然后线程1要睡 10ms,紧接着,线程2进来,这时 tickets 还是为1,因为线程1在睡,tickets 没有减 。然后线程2判断 tickets <= 0 ? 还是不成立,线程2又开始睡。同样,线程3,线程4都睡了。 这时的tickets 还是等于1的。然后线程1先醒过来,开始输出结果,tickets 减了1。可是这是其他的线程还是经过while里面的判断语句进来了的,只是睡了。所以当其他线程醒过来的时候,还是会打印出结果的。也就出现了上面的问题。
解决方法:
多线程并发改变同一变量,为了解决,采用同步代码块synchronized。里面加任意的对象,但是不能加this,因为这里创建了四个线程,每一个线程都有自己的对象,所以是四个不同的对象,没有用。所以这里不能用this,必须锁在同一个对象里才行。而Thickets.class这是唯一的。
package thread; public class Mythread { public static void main(String[] args) { Ticket sell1 = new Ticket(); Ticket sell2 = new Ticket(); Ticket sell3 = new Ticket(); Ticket sell4 = new Ticket(); sell1.setName("窗口1"); sell2.setName("窗口2"); sell3.setName("窗口3"); sell4.setName("窗口4"); sell1.start(); sell2.start(); sell3.start(); sell4.start(); } } class Ticket extends Thread { private static int tickets = 100; @Override public void run() { while(true) { synchronized (Ticket.class) {//同步代码块 if(tickets <= 0) { break; } try { Thread.sleep(100); //每100ms卖出一张 } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(getName()+":买出了第"+tickets--+"张票。"); } } } }
标签:
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com
特别注意:本站所有转载文章言论不代表本站观点,本站所提供的摄影照片,插画,设计作品,如需使用,请与原作者联系,版权归原作者所有
上一篇:抽象类和接口的区别
- 国外程序员整理的Java资源大全(全部是干货) 2020-06-12
- 2020年深圳中国平安各部门Java中级面试真题合集(附答案) 2020-06-11
- 2020年java就业前景 2020-06-11
- 04.Java基础语法 2020-06-11
- Java--反射(框架设计的灵魂)案例 2020-06-11
IDC资讯: 主机资讯 注册资讯 托管资讯 vps资讯 网站建设
网站运营: 建站经验 策划盈利 搜索优化 网站推广 免费资源
网络编程: Asp.Net编程 Asp编程 Php编程 Xml编程 Access Mssql Mysql 其它
服务器技术: Web服务器 Ftp服务器 Mail服务器 Dns服务器 安全防护
软件技巧: 其它软件 Word Excel Powerpoint Ghost Vista QQ空间 QQ FlashGet 迅雷
网页制作: FrontPages Dreamweaver Javascript css photoshop fireworks Flash