Java售票任务_多线程详细实现
题目回顾:铁道部发布了一个售票任务,要求销售1000张票,要求有3个窗口来进行销售,请编写多线程程序来模拟这个效果。
i. 窗口001正在销售第1000张票
ii. 窗口001正在销售第999张票
iii. 窗口002正在销售第998张票
iv. …
v. 窗口002正在销售第1张票
vi. 票已经销售完毕
一 、注意细节:
问题1:三个线程都卖了1000张票,一共卖了3000张票
原因:三个线程代表三个对象,就有三个成员变量(三个ticket)
解决方案:让成员变量ticket变成静态变量,因为静态变量是该类所有对象共享的变量
问题2:有些票卖了重票
原因:输出后切换到其他的线程,ticket变量没有–,所以造成了数据错误
解决方案:加锁,保证输出和ticket–运行完毕后,才能切换到其他线程
问题3:票数出现负数
原因:ticket零界点,3个线程都有可能进入
解决:在同步代码里再此判断
synchronized 同步锁、互斥锁:
注意:多个线程之间要想互斥,必须用同一把锁对象
同步代码块:
synchronized(锁对象){//上锁
…代码…
}//解锁
同步方法:
Lock锁:
二、 继承Thread接口实现
2.1 第一种解决方案:同步代码块
/*synchronized 同步锁、互斥锁:
* 注意:多个线程之间要想互斥,必须用同一把锁对象
* 同步代码块:
* synchronized(锁对象){//上锁
* ...代码...
* }//解锁
* /
public static void main(String[] args) {
myThread01 t1 = new myThread01("窗口一");
myThread01 t2 = new myThread01("窗口二");
myThread01 t3 = new myThread01("窗口三");
t1.start();
t2.start();
t3.start();
}
}
class myThread01 extends Thread{
private static int tecket = 1000;
private static Object obj= new Object();
public myThread01(String name) {
super(name);
}
@Override
public void run() {
while(tecket>0){
synchronized (obj) {
if(tecket>0){
System.out.println(Thread.currentThread().getName()+"正在销售第"+tecket+"张票");
tecket--;
}else if(tecket==0){
System.out.println(Thread.currentThread().getName()+"票已卖完");
}else{
System.out.println(Thread.currentThread().getName()+"票已卖完");
}
}
}
}
2.2 第二种解决方案:同步方法
public static void main(String[] args) {
/**
* 同步方法:
* 锁对象 -- this
* public synchronized void method01(){}
* 锁对象 -- 本类的字节码文件对象
* public synchronized static void method02(){}
*/
myThread01 t1 = new myThread01("窗口一");
myThread01 t2 = new myThread01("窗口二");
myThread01 t3 = new myThread01("窗口三");
t1.start();
t2.start();
t3.start();
}
}
class myThread02 extends Thread{
private static int tecket = 1000;
private static Object obj= new Object();
public myThread02(String name) {
super(name);
}
@Override
public void run() {
while(tecket>0){
method01();
}
}
public synchronized static void method01(){
synchronized (obj) {
if(tecket>0){
System.out.println(Thread.currentThread().getName()+"正在销售第"+tecket+"张票");
tecket--;
}else if(tecket==0){
System.out.println(Thread.currentThread().getName()+"票已卖完");
}else{
System.out.println(Thread.currentThread().getName(