Day30 线程安全之窗口售票问题(含代码)
一、需求:
铁道部发布了一个售票任务,要求销售1000张票,要求有3个窗口来进行销售,
请编写多线程程序来模拟这个效果( 注意:使用线程类的方式解决该需求)
窗口001正在销售第1张票窗口001正在销售第2张票窗口002正在销售第3张票。。。窗口002正在销售第1000张票窗口002票已售完窗口001票已售完窗口003票已售完
二、问题一
1、问题一:
三个窗口各卖1000张票,一共卖了3000张
2、相关代码:
package com.qf;public class MyThread extends Thread {public MyThread(String name) {// TODO 自动生成的构造函数存根super(name);}@Overridepublic void run() {// TODO 自动生成的方法存根int allTicket=1000;int curTicket=0;while (curTicket<allTicket) {curTicket++;System.out.println("窗口"+Thread.currentThread().getName()+"正在出售"+curTicket+"第几张票");}}
}
public class Test01 {public static void main(String[] args) {MyThread myThread1 = new MyThread("001");MyThread myThread2 = new MyThread("002");MyThread myThread3 = new MyThread("003");myThread1.start();myThread2.start();myThread3.start();}
}
出现的问题:
3、出现原因:
allTicket和curTicket是run方法的局部变量,三个线程抢到CPU资源后,都会调用run方法,run方法被调用了3次,所以卖了3000张票。
4、解决方案:
将allTicket和curTicket设置为静态变量,让三个线程共享
三、问题二
1、问题二:
有些票没有卖,有些票卖了重票
2、相关代码:
package com.qf;public class MyThread extends Thread {private static int allTicket=1000;private static int curTicket=0;public MyThread(String name) {// TODO 自动生成的构造函数存根super(name);}@Overridepublic void run() {// TODO 自动生成的方法存根while (curTicket<allTicket) {curTicket++;System.out.println("窗口"+Thread.currentThread().getName()+"正在出售"+curTicket+"第几张票");}}
}
public class Test01 {public static void main(String[] args) {MyThread myThread1 = new MyThread("001");MyThread myThread2 = new MyThread("002");MyThread myThread3 = new MyThread("003");myThread1.start();myThread2.start();myThread3.start();}
}
出现问题:
3、出现原因:
当前线程抢到CPU资源后做了票的自增,但是还没来得及输出,时间片到了就退出CPU资源,然后其他线程抢到CPU资源了。
4、解决方案:
当前线程抢到CPU资源后,票的自增和输出执行完毕才能切换到其他线程运行 – 加锁。
四、问题三
1、问题三:
多卖了票。
2、相关代码:
package com.qf;public class MyThread extends Thread {private static int allTicket=1000;private static int curTicket=0;private static Object obj = new Object();public MyThread(String name) {// TODO 自动生成的构造函数存根super(name);}@Overridepublic void run() {// TODO 自动生成的方法存根while (curTicket<allTicket) {synchronized (obj) {curTicket++;System.out.println("窗口"+Thread.currentThread().getName()+"正在出售"+curTicket+"第几张票");}}}
}
public class Test01 {public static void main(String[] args) {MyThread myThread1 = new MyThread("001");MyThread myThread2 = new MyThread("002");MyThread myThread3 = new MyThread("003");myThread1.start();myThread2.start();myThread3.start();}
}
出现问题:
3、出现原因:
curTicket到了临界点(999),三个线程都可以进判断,然后上锁。
4、解决方案:
在锁中再次判断。
完整代码:
package com.qf;public class MyThread extends Thread {private static int allTicket=1000;private static int curTicket=0;private static Object obj = new Object();public MyThread(String name) {// TODO 自动生成的构造函数存根super(name);}@Overridepublic void run() {// TODO 自动生成的方法存根while (curTicket<allTicket) {synchronized (obj) {if(curTicket < allTicket){curTicket++;System.out.println("窗口" + Thread.currentThread().getName() + "正在销售第" + curTicket + "张票");}if(curTicket >= allTicket){System.out.println("窗口" + Thread.currentThread().getName() + "票已经售完");}}}}
}
public class Test01 {public static void main(String[] args) {MyThread myThread1 = new MyThread("001");MyThread myThread2 = new MyThread("002");MyThread myThread3 = new MyThread("003");myThread1.start();myThread2.start();myThread3.start();}
}args) {MyThread myThread1 = new MyThread("001");MyThread myThread2 = new MyThread("002");MyThread myThread3 = new MyThread("003");myThread1.start();myThread2.start();myThread3.start();}
}