2025-07-10

昨天有人在群裡說瞭一個多線程售票的問題,當時沒怎麼註意,後來沒事就自己做瞭一下,開始還覺得應該很簡單,最後昨天都沒做出來,今天早上在床上突然思路開闊,起來就完成瞭,唉,感嘆啊,有時候還真的要睡睡,這種事情在我身上都發生好幾次瞭,每次都是睡覺起來問題就可以解決瞭,呵呵。。。
我模擬的是一個自動售票機,當然可能程序還又bug,但先考慮這麼多吧,我假設來買票的人是還算是個理性點的啊
模擬的是一臺機器,其他都是人來這臺機器買票,票是5元一張,買的時候可以說買多少張,然後給錢,程序自動售票並找零。顧客交瞭前後首先機器有個收錢的方法,這個方法是按照一定的原則來的,他會把錢按5、10、20、50、100分開來裝,但由於錢的分發很多,我就采用瞭一個比較簡單的機器會按從大到小來分錢,比如你給他55他就會分為50和5,你給35它就會氛圍20+10+5,給45就是2*20+5。這就是機器收錢分開裝瞭。
接著就是找零瞭,機器也有個找零的方法,根據要找的餘額來看機器裡面是否有相應的錢數,有就直接找瞭,沒有就還要等待,等另外有人來買票,有對應的錢瞭才可以找。比如你開始去買1張票,但你給瞭10元,剛開張,機器裡面沒有5元的票子,機器肯定找不出來,他就會讓你等,如果下一個人買票時候給瞭5元的票子,那麼機器就可以找你錢瞭,大致情況就是這樣啦。貼一下代碼吧,以後自己也可以看看,說不定哪天自己就不小心刪掉瞭。
機器代碼:
 
Java代碼 
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(); 
                } 
            } 
        } 
    } 

 買票人:
 
Java代碼 
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); 
    } 

 對於那些找零機器裡沒錢找的找零線程代碼:
 
Java代碼 
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; 
                } 
            } 
        } 
    } 

 測試代碼瞭:
 
Java代碼 
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(); 
    } 
 

作者“l555iu”
 

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *