Day30 线程安全之窗口售票问题(含代码)

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);
	}
	@Override
	public 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);
	}
	@Override
	public 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);
	}
	@Override
	public 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);
	}
	@Override
	public 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();
	}
}

相关推荐

  1. Day31 线安全

    2024-04-07 06:16:02       23 阅读
  2. Day32 线安全

    2024-04-07 06:16:02       35 阅读

最近更新

  1. docker php8.1+nginx base 镜像 dockerfile 配置

    2024-04-07 06:16:02       94 阅读
  2. Could not load dynamic library ‘cudart64_100.dll‘

    2024-04-07 06:16:02       101 阅读
  3. 在Django里面运行非项目文件

    2024-04-07 06:16:02       82 阅读
  4. Python语言-面向对象

    2024-04-07 06:16:02       91 阅读

热门阅读

  1. 【算法-数组】二分查找法

    2024-04-07 06:16:02       49 阅读
  2. Php中依赖注入是怎样的

    2024-04-07 06:16:02       43 阅读
  3. 34-2 SSRF(服务器端请求伪造)漏洞 - SSRF相关函数

    2024-04-07 06:16:02       45 阅读
  4. React Native调用Android的原生功能

    2024-04-07 06:16:02       35 阅读
  5. SpringBoot 优雅的网络请求

    2024-04-07 06:16:02       34 阅读
  6. spring 和springBoot区别

    2024-04-07 06:16:02       26 阅读
  7. 期权的各种套利分类

    2024-04-07 06:16:02       35 阅读
  8. 效率系列(十) macOS软件管理工具

    2024-04-07 06:16:02       33 阅读
  9. 设计模式:策略模式示例

    2024-04-07 06:16:02       29 阅读
  10. 计算机网络路由的配置

    2024-04-07 06:16:02       34 阅读
  11. C语言预处理基础知识笔记

    2024-04-07 06:16:02       34 阅读
  12. YOLOv5实战记录03 数据集构建

    2024-04-07 06:16:02       30 阅读
  13. go | gin多服务 | goroutine | ReadTimeout&WriteTimeout

    2024-04-07 06:16:02       38 阅读
  14. ffmpeg 从现有视频中截取一段

    2024-04-07 06:16:02       37 阅读