Java多线程电影院,java 22 - 11 多线程之模拟电影院售票口售票

使用多线程实现的第二种方式:

首先创建自定义类

1 public class SellTicket implementsRunnable {2 //定义100张票

3 private int ticket = 100;4

5 public voidrun() {6

7 //假设一直在售票

8 while(true){9 //现实中买票时,都会有延迟的,所以让线程休息下

10 try{11 Thread.sleep(100);12 } catch(InterruptedException e) {13 e.printStackTrace();14 }15 if(ticket > 0){16 System.out.println(Thread.currentThread().getName()+"正在出售第"+(ticket--)+"张票");17 }18 19 }20 }21 }

创建测试类,售票口设置3个:

1 public classSellTicket1Demo {2

3 public static voidmain(String[] args) {4

5 //创建资源对象

6 SellTicket st = newSellTicket();7

8 //创建三个线程对象

9 Thread st1 = new Thread(st,"售票口1");10 Thread st2 = new Thread(st,"售票口2");11 Thread st3 = new Thread(st,"售票口3");12

13 //启动线程

14 st1.start();15 st2.start();16 st3.start();17

18 }19

20 }

当启动程序后,就会发现出现了2个问题:

第一个问题:会出现2个或者3个售票口同时出售同一张票的情况(售票口1、2、3同时出售第90张票)

第二个问题:到最后面,甚至售票口在出售第0张、第-1张票

分析原因:

第一个问题:会出现2个或者3个售票口同时出售同一张票的情况(售票口1、2、3同时出售第90张票)

首先我们假设出现了第一个和的第二个售票口同时出售第100张票:

原因:

因为线程默认的优先级都是5,一样的,都要抢占资源,这里为了方便解析,设 st1 > st2 。

我们的理想状况是:st1出售第100张票,st2出售第99张票。

但是,由于CPU的每一次执行必须是个原子性的操作。

原子性:最简单基本的操作,比如说i=100,System.out.println(i); 这个就是最简单基本的操作,不能拆分的,而i--就不是了。

所以,当程序走到

System.out.println(Thread.currentThread().getName() + "正在出售第"+ (ticket--) + "张票");

A: CPU会先记录之前的值(这里是ticket=100)

B: 接着才ticket--

C: 然后输出原来的值(但是,在CPU执行这个过程时,st2闯进来了)

D: ticket变成99

E: st1出售第100张票

F:由于C步骤时,st2闯进去了。所以st2出售第100张票

根本原因:CPU的每一次执行必须是个原子性的操作。

第二个问题:到最后面,甚至售票口在出售第0张、第-1张票

我们假设最差的情况:窗口1出售第1张票,窗口2出售第0张票,窗口3出售第-1张票:(依旧是假设抢占到资源的顺序是 st1 > st2 > st3)

原因:

在走到

hread.sleep(100); //t1进来了并休息,t2进来了并休息,t3进来了并休息,

注意:在走到这里的时候,这3个都带着一个变量:ticket = 1; 进来了(具体原因后面说)

所以,在执行

System.out.println(Thread.currentThread().getName() + "正在出售第"+ (ticket--) + "张票");

结果:

窗口1出售第1张票,ticket = 0;

窗口2出售第0张票,ticket = -1;

窗口3出售第-1张票, ticket = -2;

当然,这是最差的情况。有可能就窗口2跟进来,也有可能就窗口1进来。

但是,你不能把期望放在有可能上面。

根本原因:随机性和延迟

随机性(这里是不知道几个线程跟着进来)和延迟导致(这里是判断延迟)

总的说,这两个根本原因其实就是:线程的安全问题。

线程安全问题在理想状态下,是不容易出现的,但是一旦出现了,对软件的影响非常大。

所以,我们要解决线程安全问题。

原文:http://www.cnblogs.com/LZL-student/p/5935172.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值