首先看题目描述:

假设有火车票100张,创建4个线程模拟4个售票点,每100ms售出一张,打印出售票过程,格式如下:

窗口3:卖出第100张票

窗口4:卖出第99张票

............

............

简单的思路就是创建一个类,首先肯定要去继承Thread。开启线程,由于是4个窗口,肯定要开启4个线程。然后让每个线程去输出结果,也就是卖出去的票。这里很多人想不到如何让4个线程不打印重复的票。(比如4个线程都卖出去了第100张票,这显然是不合理的)。

看代码:

  

 package com.lesson.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;//这里设置成static,目的是让每个线程共享这个变量。以免出现重复打印的现象。
@Override
public void run() {
while(true) {
if(tickets <= 0) {
break;
}
29     System.out.println(getName()+":买出第"+tickets--+"张票。");//卖出一张减一张票
}
} }

可能你已经看到了你想要的结果了。但是,还没完。目前代码写到这里是有问题的!!!

为什么?

看下面的代码:

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--+"张票。");
}
}
}
}

最新文章

  1. openswan-ipsec.conf配置说明
  2. Tempter of the Bone
  3. DOM扩展之HTML5 插入标记
  4. HTML5 History API实现无刷新跳转
  5. ROS 新手常见问题汇总
  6. Sqli-LABS通关笔录-12
  7. Tuple的用法
  8. ORACLE 默认密码确认
  9. Android - 代码片段
  10. ajax 异步上传视频带进度条并提取缩略图
  11. 集中式(CVS、SVN)VS分布式(Git)
  12. 【系统设计】论文总结之:Butler W. Lampson. Hints for computer system design
  13. linux环境vnc部署过程详解
  14. N厂劳力士黑水鬼V7出了1年,如今依旧被追捧,供不应求
  15. Python的文件及异常
  16. CSS奇淫技巧
  17. 【Java编程思想笔记】-集合2
  18. Node总结 模块机制
  19. TensorFlow深度学习实战---MNIST数字识别问题
  20. C# 处理XML的基本操作

热门文章

  1. VUE随笔-20181020
  2. java集合类学习笔记之HashMap
  3. NFS共享服务
  4. UIEvent笔记
  5. PHP curl 上传文件版本兼容问题
  6. 搭建自己的pypi私有源服务器
  7. [BZOJ 4890][TJOI2017]城市
  8. ZOJ - 3939 The Lucky Week(日期循环节+思维)
  9. linux忘记root密码怎么办
  10. sql 性能优化相关--总结别人的总结,未做验证,先归纳