昨天有人在群里说了一个多线程售票的问题,当时没怎么注意,后来没事就自己做了一下,开始还觉得应该很简单,最后昨天都没做出来,今天早上在床上突然思路开阔,起来就完成了,唉,感叹啊,有时候还真的要睡睡,这种事情在我身上都发生好几次了,每次都是睡觉起来问题就可以解决了,呵呵。。。
我模拟的是一个自动售票机,当然可能程序还又bug,但先考虑这么多吧,我假设来买票的人是还算是个理性点的啊
模拟的是一台机器,其他都是人来这台机器买票,票是5元一张,买的时候可以说买多少张,然后给钱,程序自动售票并找零。顾客交了前后首先机器有个收钱的方法,这个方法是按照一定的原则来的,他会把钱按5、10、20、50、100分开来装,但由于钱的分发很多,我就采用了一个比较简单的机器会按从大到小来分钱,比如你给他55他就会分为50和5,你给35它就会氛围20+10+5,给45就是2*20+5。这就是机器收钱分开装了。
接着就是找零了,机器也有个找零的方法,根据要找的余额来看机器里面是否有相应的钱数,有就直接找了,没有就还要等待,等另外有人来买票,有对应的钱了才可以找。比如你开始去买1张票,但你给了10元,刚开张,机器里面没有5元的票子,机器肯定找不出来,他就会让你等,如果下一个人买票时候给了5元的票子,那么机器就可以找你钱了,大致情况就是这样啦。贴一下代码吧,以后自己也可以看看,说不定哪天自己就不小心删掉了。
机器代码:
package com.thread;
import java.util.HashMap;
import java.util.Map;
public class TicketMachine {
private int ticket = 20;
private Map<String,Integer> balance = new HashMap<String,Integer>();
public final float TICKET_PRICE = 5.0F;
public float[] type = {5.0F , 10.0F , 20.0F , 50.0F , 100.0F};
public String[] strType={"五元" , "十元" , "二十元" , "五十元" , "一百元"};
public int getTicket(){
return ticket;
}
public void setTicket(int ticket){
this.ticket=ticket;
}
public Map getBalance(){
return this.balance;
}
//假设给的钱都是5的倍数
public void separate(float money){
//判断money是否是5的倍数,不是就舍去个位数转成5的倍数
float temp=money/5;
money=5*temp;
for(int i=0;i<this.type.length;i++){
if(money<=type[i]){ //票只卖100以内
if(money==type[i]){
this.save(this.strType[i],1);
}else{
float temp1,temp2,temp3,temp4;
if((temp1=money/50)>0){
this.save(this.strType[3],(int)temp1);
money-=50*(int)temp1;
}
if((temp2=money/20)>0){
this.save(this.strType[2],(int)temp2);
money-=20*(int)temp2;
}
if((temp3=money/10)>0){
this.save(this.strType[1],(int)temp3);
money-=10*(int)temp3;
}
if((temp4=money/5)>0){
this.save(this.strType[0],(int)temp4);
money-=5*(int)temp4;
}
}
break;
}
}
}
//向balance一张一张的存钱
public void save(String str,int add){
Integer num= (Integer) this.getBalance().get(str);
if(num==null){
num=0;
}
this.balance.put(str, num+add);
}
//从balance中取钱找零
//sdel是应该减掉的数,它=del*type[str的地址],del是减去的次数
//如果失败map应该要恢复原样的
public float delete(String str,int del,float sdel,Map<String,Integer> tempMap){
Integer num= tempMap.get(str);
if(num==null||num<1){
return sdel;
}else{
if(num>del){
tempMap.put(str, num-del);
return 0.0F;
}else{
tempMap.put(str, 0);
int temp=0;
for(int i=0;i<this.strType.length;i++){
if(str.equals(strType[i])){
temp=i;
}
}
return this.type[temp]*(del-num);
}
}
}
public boolean change(float result){
//判断money是否是5的倍数,不是就舍去个位数转成5的倍数
float temp=result/5;
result=5*temp;
//操作的map只是暂时的,如果返回的是false那么要恢复到原来的
Map<String,Integer> tempMap = new HashMap<String, Integer>();
tempMap.putAll(this.balance);
for(int i=0;i<this.type.length;i++){
if(result<=type[i]){ //票只卖100以内
if(result==type[i]){
result-=type[i];
result+=this.delete(this.strType[i],1,type[i],tempMap);
}else{
float temp1,temp2,temp3,temp4;
if((temp1=result/50)>0){
result-=50*(int)temp1;//应该减去这么多的
result+=this.delete(this.strType[3],(int)temp1,50*(int)temp1,tempMap);//加上没有减掉的
}
if((temp2=result/20)>0){
result-=20*(int)temp2;
result+=this.delete(this.strType[2],(int)temp2,20*(int)temp2,tempMap);
}
if((temp3=result/10)>0){
result-=10*(int)temp3;
result+=this.delete(this.strType[1],(int)temp3,10*(int)temp3,tempMap);
}
if((temp4=result/5)>0){
result-=5*(int)temp4;
result+=this.delete(this.strType[0],(int)temp4,10*(int)temp4,tempMap);
}
}
if(result==0.0){
this.balance=null;
this.balance=tempMap;
return true;
}else{
return false;
}
}
}
return false;
}
//售票
public synchronized void saleTicket(int count,float money){
float sum=count*this.TICKET_PRICE;//购买票需要总金额
float result=0.0F;//应找零
if(money<sum){
System.out.println(Thread.currentThread().getName()+"退还钱,对不起,你的金额不足买"+count+"张票");
return;
}else if(count>this.getTicket()){
System.out.println(Thread.currentThread().getName()+"退还钱,对不起,今天的票只剩下"+this.getTicket()+"张了");
return;
}else{
this.separate(money);
result=money-sum;
}
if(result==0.0){
System.out.println(Thread.currentThread().getName()+"恭喜你买票成功,谢谢惠顾");
return;
}else{
if(this.change(result)){
System.out.println(Thread.currentThread().getName()+"应找你"+result+"元,请收好找零,欢迎下次惠顾");
}else{
Thread changeTask=new ChangeTask(this,result);//后台找零程序
changeTask.setDaemon(true);//设置为后台线程,需要在start之前
changeTask.start();
try {
System.out.println(Thread.currentThread().getName()+"请等待。。。");
this.wait();//暂停等待
System.out.println(Thread.currentThread().getName()+"对不起让你久等了,现在有零钱了,应找你"+result+"元,欢迎下次惠顾");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
买票人:
package com.thread;
import java.util.Timer;
public class BuyTicket extends Thread{
//售票机
private TicketMachine machine;
//购票数
private int count;
//买票钱
private float money;
//姓名
//private String name;
public BuyTicket(){
}
public BuyTicket(TicketMachine machine, int count, float money,String name) {
super(name);
this.machine = machine;
this.count = count;
this.money = money;
//this.name = name;
System.out.println(name+":帮我买"+count+"张票");
}
public void run() {
machine.saleTicket(count, money);
}
}
对于那些找零机器里没钱找的找零线程代码:
package com.thread;
public class ChangeTask extends Thread {
private TicketMachine machine;
private final float result;
public ChangeTask(TicketMachine machine,float result){
this.machine=machine;
this.result=result;
}
@Override
public void run() {
//System.out.println("找零任务线程运行了。。。");
while(true){
synchronized (machine) {
if(machine.change(result)){
machine.notifyAll();
//System.out.println("已经通知了");
break;
}
}
}
}
}
测试代码了:
package com.thread;
public class Test {
public static void main(String[] args) {
TicketMachine machine=new TicketMachine();
BuyTicket buy1=new BuyTicket(machine,1,5.0F,"张三");
BuyTicket buy2=new BuyTicket(machine,3,15.0F,"李四");
BuyTicket buy3=new BuyTicket(machine,5,33.0F,"王五");
BuyTicket buy4=new BuyTicket(machine,6,50.0F,"赵六");
buy1.start();
buy2.start();
buy3.start();
buy4.start();
}
}
分享到:
相关推荐
JAVA多线程售票系统 本资源摘要信息将围绕JAVA多线程售票系统展开,涵盖多线程编程、同步机制和售票系统的设计思想。 多线程编程 在JAVA中,多线程编程是指在一个程序中使用多个线程来执行不同的任务,以提高程序...
多线程+售票案例 在软件开发中,多线程是一种非常重要的概念,它可以大大提高程序的执行效率和响应速度。在这个文件中,我们将详细介绍多线程的概念、特点、创建方法、线程状态、线程之间的关系等知识点,并通过...
在这个问题中,我们关注的是如何利用Java的多线程特性来创建一个高效、安全的售票系统,该系统能够处理不同面值的票和找零操作。 首先,我们需要理解多线程的基本概念。在Java中,通过`Thread`类或者实现`Runnable`...
总之,这个“自动售票机VHDL”项目涵盖了VHDL语言的基础应用,硬件描述的层次化设计,以及算法设计和错误处理等多个方面,对于理解和掌握数字系统设计有着重要的实践价值。通过完成这样的项目,开发者可以深入了解...
### 火车票售票系统创建多线程 在计算机科学领域中,多线程技术被广泛应用于提高软件系统的响应速度、并发处理能力和资源利用率。本文将基于给定的代码片段,详细介绍如何在一个简单的火车票售票系统中实现多线程。...
假设开始售票时售票处没有零钱可以找零。 问这2n个人有多少种排队方式,不至使售票处出现找不出零的局面? 例如当n=3时,共6人,3人持50元,3人持100元。可以找零的排队方式有如下5种: 50 50 50 100 100 100 50 50...
"多线程设计一个火车售票模拟程序" 在本实验中,我们将使用 Java 语言来设计一个火车售票模拟程序。这个程序模拟了火车站中的售票情况,具有5个售票点,每个售票点都可以售出火车票。我们将使用多线程技术来实现这...
在本文中,我们将深入探讨如何使用多线程技术来模拟火车站售票系统,主要涉及C++编程语言中的线程同步和Windows编程。多线程技术在处理并发任务时能显著提高程序效率,尤其在大型系统中,如火车站售票系统,它需要...
本教程将聚焦于使用Delphi这一强大的Windows应用程序开发工具来实现多线程,特别是模拟一个售票系统,以展示多线程如何在实际场景中应用。 Delphi是Borland公司(现Embarcadero Technologies)推出的一款集成开发...
### Java多线程同步机制在售票系统的实现 #### 一、引言 随着计算机硬件的发展,多核处理器已经成为主流配置,这为多线程编程提供了更广阔的应用场景。多线程能够充分利用多核处理器的优势,提高程序的并发性和...
在计算机科学领域,多线程是一种...总结来说,"多线程售票系统"涉及了线程的创建、线程入口函数、线程同步与通信、异常处理、资源管理等多个关键概念。理解和正确应用这些概念对于构建高效、稳定的并发系统至关重要。
java课程学习多线程中模仿火车站多窗口同时售票的场景,适合初学者学习
该系统可以出售2条线路3种不同价位的票,完成售票、找零、显示等功能。 知识点1:FPGA(Field-Programmable Gate Array)是可编程逻辑器件,具有高速、灵活、可靠等特点,广泛应用于数字系统设计。 知识点2:EDA...
在本实验中,我们探讨了如何使用C语言和Windows API实现多线程来模拟汽车司机与售票员的同步操作。这个实验旨在展示并发执行的线程如何通过同步机制协同工作,确保程序的正确运行。 首先,多线程是操作系统中的一种...
4. **多线程处理**:在售票过程中,可能有多个用户同时进行操作,因此系统需要支持多线程。Java的并发库提供了丰富的线程控制工具,如Thread类、Runnable接口、ExecutorService等,用于实现并发安全的售票服务,避免...
运用java语言编写 java多线程 模仿车站售票系统
在“数字电路课程设计(自动售票机)”中,学生将深入学习并应用数字电路的基本原理来构建一个模拟自动售票机的系统。这个项目旨在帮助学生掌握数字逻辑、微处理器控制以及接口技术的关键概念,这些都是现代电子系统...
### 售票窗口模拟线程同步:深入解析与实现 在多线程环境中,线程同步是一项关键的技术,用于确保多个线程访问共享资源时的正确性和一致性,避免资源竞争和数据不一致等问题。本文将通过一个具体的案例——售票窗口...
在Java编程中,"并发售票_多线程_并发"是一个重要的概念,它涉及到如何在多处理器或多核心系统中高效地执行多个任务。在这个主题下,我们将深入探讨Java中的多线程和并发处理机制。 一、多线程 多线程是Java的核心...