Java实验四,星号题最终版(暂定。。。也许还能找到问题)

1、 第一版使用wait、notifyAll、synchronized ,可以买到票但是排序不行

只能支持输入仅有n张五元钱其余为0张
或者仅有n张10元钱,其余为0张
或者仅有n张20元钱,其余为0张

主要执行函数:
giveChange():
用 sychronized 关键字加对象锁,无法找零或者钱不够买票的时候,线程wait
否则进行找零或者直接出票,然后执行 notifyALL方法,尝试唤醒所有线程,当被wait的线程发现资源已经满足,可以找零的时候,开始再次加入自由抢占的线程大军
实现的功能:大概率确保能买票
还没实现的功能:按顺序排队买票的顺序
在这里插入图片描述

package Ex4.Thirdquestion;

/**
 * @author 15328
 * *3、编写Java应用程序模拟5个人排队买票。
 * 售票员只有1张五元的钱,电影票五元钱一张。
 * 假设5个人的名字及排队顺序是:赵、钱、孙、李、周。
 * “赵”拿1张二十元的人民币买2张票,
 * “钱”拿1张二十元的人民币买1张票,
 * “孙”1张十元的人民币买1张票,
 * “李”拿1张十元的人民币买2张票,
 * “周”拿1张五元的人民币买1张票。
 * 要求售票员按如下规则找赎:
 * (1)二十元买1张票,找零:1张十元;不许找零2张五元。
 * (2)二十元买1张票,找零:1张十元,1张五元;不许找零3张五元。
 * (3)十元买一张票,找零1张五元。
 */
public class Buy extends Thread {

    Money money;

    private  int fiveOfNumber;
    private  int tenOfNumber;
    private  int twentyOfNumber;
    private int ticketOfNum;
    private String name;
    public Buy(Money money,int fiveOfNumber, int tenOfNumber, int twentyOfNumber,int ticketOfNum,String name) {
        this.fiveOfNumber = fiveOfNumber;
        this.tenOfNumber = tenOfNumber;
        this.twentyOfNumber = twentyOfNumber;
        this.ticketOfNum = ticketOfNum;
        this.money = money;
        this.name = name;
    }


    @Override
    public void run() {
        try {
            Thread.currentThread().setName(this.name);
            money.givechange(fiveOfNumber,tenOfNumber,twentyOfNumber,ticketOfNum,Thread.currentThread().getName());
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}




class Money{
    private  static int fiveOfNum = 1;
    private  static int tenOfNum = 0;
    private  static int twentyOfNum = 0;

    public  synchronized void givechange(int fiveOfNumber,int tenOfNumber,int twentyOfNumber,int ticketOfNumber,String name) throws InterruptedException {
        System.out.print(name+ " ");
        if(fiveOfNumber !=0 && tenOfNumber==0 && twentyOfNumber==0) {
            if(ticketOfNumber > fiveOfNumber) {
                System.out.println("钱不够买票");
                return;
            }
            else {
                System.out.print("客户原有" + fiveOfNumber + "张5元," + ",买票总钱数是:" + (ticketOfNumber * 5));
                fiveOfNumber -= ticketOfNumber;
                fiveOfNum += ticketOfNumber;
                System.out.println(", 客户现有" + fiveOfNumber + "张5元" + ", 客户现有" + tenOfNumber + "张10元"
                        + ", 客户现有" + twentyOfNumber + "张20元" + " 不用找零,现在售货员剩余五元:" + fiveOfNum + "张"
                        + " 、十元: " + tenOfNum + "张" + " 、 二十元: " + twentyOfNum + "张");
                this.notifyAll();
            }
        }
        else
        if(fiveOfNumber==0 && tenOfNumber!=0 && twentyOfNumber==0) {
            if(ticketOfNumber*5 > tenOfNumber*10){
                System.out.println("钱不够买票");
                return;
            }
            else{
                if(ticketOfNumber % 2 == 0) {
                    System.out.print("客户原有" + tenOfNumber + "张10元," + ",买票总钱数是:" + (ticketOfNumber * 5));
                    tenOfNumber -= ticketOfNumber / 2;
                    tenOfNum += ticketOfNumber / 2;
                    System.out.println(", 客户现有" + fiveOfNumber + "张5元" + ", 客户现有" + tenOfNumber + "张10元"
                            + ", 客户现有" + twentyOfNumber + "张20元" + " 不用找零,现在售货员剩余五元:" + fiveOfNum + "张"
                            + " 、十元: " + tenOfNum + "张" + " 、 二十元: " + twentyOfNum + "张");
                    this.notifyAll();
                }
                else{
                    //买奇数张票,有一张需要找零
                    if(fiveOfNum <= 0) {
                        System.out.println("要找零一张五元钱,但是没有,线程睡眠");
                        Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
                        this.wait();
                        //Thread.sleep(5);
                        System.out.print(name+ " ");
                    }
                    if(!(fiveOfNum <= 0)) {
                        System.out.print("客户原有" + tenOfNumber + "张10元," + ",买票总钱数是: " + (ticketOfNumber * 5));
                        fiveOfNum--;
                        fiveOfNumber++;
                        tenOfNum += (ticketOfNumber + 1) / 2;
                        tenOfNumber -= (ticketOfNumber + 1) / 2;
                        System.out.println(", 客户现有" + fiveOfNumber + "张5元" + ", 客户现有" + tenOfNumber + "张10元"
                                + ", 客户现有" + twentyOfNumber + "张20元" + " 找零5元,现在售货员剩余五元:" + fiveOfNum + "张"
                                + " 、十元: " + tenOfNum + "张" + " 、 二十元: " + twentyOfNum + "张");
                        this.notifyAll();
                    }
                }
            }
        }
        else
        if(fiveOfNumber==0 && tenOfNumber==0 && twentyOfNumber!=0){
            if(ticketOfNumber * 5 > twentyOfNumber * 20) {
                System.out.println("钱不够买票");
                return;
            }
            else{
                if(ticketOfNumber % 2 == 0) {
                    if(ticketOfNumber >= 4 && ticketOfNumber%4 == 0) {
                        //4的倍数
                        System.out.print("客户原有" + twentyOfNumber + "张20元," + ",买票总钱数是: " + (ticketOfNumber * 5));
                        twentyOfNumber -= ticketOfNumber / 4;
                        twentyOfNum += ticketOfNumber / 4;
                        System.out.println(", 客户现有" + fiveOfNumber + "张5元" + ", 客户现有" + tenOfNumber + "张10元"
                                + ", 客户现有" + twentyOfNumber + "张20元" + " 不用找零,现在售货员剩余五元:" + fiveOfNum + "张"
                                + " 、十元: " + tenOfNum + "张" + " 、 二十元: " + twentyOfNum + "张");
                        this.notifyAll();
                    }
                    else{
                        //只是2的倍数,不是4的倍数,找一张10元零钱
                        //2、6、10、14、
                        System.out.print("客户原有" + twentyOfNumber + "张20元,"+",买票总钱数是: " + (ticketOfNumber * 5)  );
                        if(tenOfNum <= 0) {
                            System.out.println("要找零一张十元钱,但是没有,线程睡眠");
                            Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
                            this.wait();
                            //Thread.sleep(5);
                            System.out.print(name+ " ");
                        }
                        if(!(tenOfNum <= 0)) {
                            tenOfNum--;
                            tenOfNumber++;
                            twentyOfNum += (ticketOfNumber + 2) / 4;
                            twentyOfNumber -= (ticketOfNumber + 2) / 4;
                            System.out.print("客户原有" + twentyOfNumber + "张20元,"+",买票总钱数是: " + (ticketOfNumber * 5)  );
                            System.out.println(", 客户现有" + fiveOfNumber + "张5元" + ", 客户现有" + tenOfNumber + "张10元"
                                    + ", 客户现有" + twentyOfNumber + "张20元" + " ,要找零10元,现在售货员剩余五元:" + fiveOfNum + "张"
                                    + " 、十元: " + tenOfNum + "张" + " 、 二十元: " + twentyOfNum + "张");
                            this.notifyAll();
                        }
                    }
                }
                else {
                    //不是2的倍数的时候
                    if((ticketOfNumber - 1) % 4 == 0) {
                        //1、5、9、、、、、
                        if(tenOfNum <= 0 || fiveOfNum <= 0) {
                            System.out.println("要找零一张五元钱和一张十元钱,但是没有,线程睡眠");
                            Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
                            this.wait();
                            //Thread.sleep(5);
                            System.out.print(name+ " ");
                        }
                        if(!(tenOfNum <= 0 || fiveOfNum <= 0)){
                            System.out.print("客户原有" + twentyOfNumber + "张20元," + ",买票总钱数是: " + (ticketOfNumber * 5));
                            fiveOfNum--;
                            fiveOfNumber++;
                            tenOfNum--;
                            tenOfNumber++;
                            twentyOfNumber -= (ticketOfNumber / 4 + 1);
                            twentyOfNum += (ticketOfNumber / 4 + 1);
                            System.out.println(", 客户现有" + fiveOfNumber + "张5元" + ", 客户现有" + tenOfNumber + "张10元"
                                    + ", 客户现有" + twentyOfNumber + "张20元" + " ,要找零一张10元和一张五元,现在售货员剩余五元:" + fiveOfNum + "张"
                                    + " 、十元: " + tenOfNum + "张" + " 、 二十元: " + twentyOfNum + "张");
                            this.notifyAll();
                        }
                    } else if((ticketOfNumber + 1) % 4 == 0) {
                        //3、7、11、、、、、
                        if(fiveOfNum <= 0) {
                            System.out.println("要找零一张五元钱,但是没有,线程睡眠");
                            Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
                            this.wait();
                            //Thread.sleep(5);
                            System.out.print(name+ " ");
                        }
                        if(!(fiveOfNum <= 0)){
                            System.out.print("客户原有" + twentyOfNumber + "张20元," + ",买票总钱数是: " + (ticketOfNumber * 5));
                            fiveOfNum--;
                            fiveOfNumber++;
                            twentyOfNumber -= (ticketOfNumber / 4 + 1);
                            twentyOfNum += (ticketOfNumber / 4 + 1);
                            System.out.println(", 客户现有" + fiveOfNumber + "张5元" + ", 客户现有" + tenOfNumber + "张10元"
                                    + ", 客户现有" + twentyOfNumber + "张20元" + " ,要找零一张五元,现在售货员剩余五元:" + fiveOfNum + "张"
                                    + " 、十元: " + tenOfNum + "张" + " 、 二十元: " + twentyOfNum + "张");
                            this.notifyAll();
                        }
                    }
                }
            }
        }
    }

}

class TicketSeller{
    public static void main(String[] args) {
        Money money = new Money();


        /*new Buy(money, 0, 4, 0,3,"1号").start();
        new Buy(money, 0, 0, 1,3,"2号").start();
        new Buy(money, 0, 0, 1,1,"3号").start();
        new Buy(money, 0, 1, 0,2,"4号").start();
        new Buy(money, 0, 3, 0,4,"5号").start();
        new Buy(money, 3, 0, 0,3,"6号").start();
        new Buy(money, 3, 0, 0,4,"7号").start();
        new Buy(money, 0, 0, 2,4,"8号").start();
        new Buy(money, 0, 0, 2,8,"9号").start();
        new Buy(money, 0, 0, 2,7,"10号").start();*/


        new Buy(money, 0, 0, 1,2,"赵").start();
        new Buy(money, 0, 0, 1,1,"钱").start();
        new Buy(money, 0, 1, 0,1,"孙").start();
        new Buy(money, 0, 1, 0,2,"李").start();
        new Buy(money, 1, 0, 0,1,"周").start();
    }
}

2、 第二版 第一次使用公平锁、ReentrantLock、Condition,感觉还是没解决排序问题

在这里插入图片描述

import java.util.Date;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author 15328
 * *3、编写Java应用程序模拟5个人排队买票。
 * 售票员只有1张五元的钱,电影票五元钱一张。
 * 假设5个人的名字及排队顺序是:赵、钱、孙、李、周。
 * “赵”拿1张二十元的人民币买2张票,
 * “钱”拿1张二十元的人民币买1张票,
 * “孙”1张十元的人民币买1张票,
 * “李”拿1张十元的人民币买2张票,
 * “周”拿1张五元的人民币买1张票。
 * 要求售票员按如下规则找赎:
 * (1)二十元买1张票,找零:1张十元;不许找零2张五元。
 * (2)二十元买1张票,找零:1张十元,1张五元;不许找零3张五元。
 * (3)十元买一张票,找零1张五元。
 */
public class Buy extends Thread {

    Money money;

    private  int fiveOfNumber;
    private  int tenOfNumber;
    private  int twentyOfNumber;
    private int ticketOfNum;
    private String name;
    public Buy(Money money,int fiveOfNumber, int tenOfNumber, int twentyOfNumber,int ticketOfNum,String name) {
        this.fiveOfNumber = fiveOfNumber;
        this.tenOfNumber = tenOfNumber;
        this.twentyOfNumber = twentyOfNumber;
        this.ticketOfNum = ticketOfNum;
        this.money = money;
        this.name = name;
    }


    @Override
    public void run() {
        Thread.currentThread().setName(this.name);
        money.givechange(fiveOfNumber,tenOfNumber,twentyOfNumber,ticketOfNum,Thread.currentThread().getName());
    }
}




class Money{
    private  static int fiveOfNum = 1;
    private  static int tenOfNum = 0;
    private  static int twentyOfNum = 0;

    public Lock lock;
    public Condition condition;
    public Money(boolean fair){
        lock = new ReentrantLock(fair);
        condition = lock.newCondition();
    }


        public  void givechange(int fiveOfNumber,int tenOfNumber,int twentyOfNumber,int ticketOfNumber,String name) {
            try {
                lock.lock();
                System.out.print(name + " ");
                if(fiveOfNumber != 0 && tenOfNumber == 0 && twentyOfNumber == 0) {
                    if(ticketOfNumber > fiveOfNumber) {
                        System.out.println("钱不够买票");
                        lock.unlock();
                        return;
                    } else {
                        System.out.print("客户原有" + fiveOfNumber + "张5元," + ",买票总钱数是:" + (ticketOfNumber * 5));
                        fiveOfNumber -= ticketOfNumber;
                        fiveOfNum += ticketOfNumber;
                        System.out.println(", 客户现有" + fiveOfNumber + "张5元" + ", 客户现有" + tenOfNumber + "张10元"
                                + ", 客户现有" + twentyOfNumber + "张20元" + " 不用找零,现在售货员剩余五元:" + fiveOfNum + "张"
                                + " 、十元: " + tenOfNum + "张" + " 、 二十元: " + twentyOfNum + "张");
                        condition.signalAll();
                    }
                } else if(fiveOfNumber == 0 && tenOfNumber != 0 && twentyOfNumber == 0) {
                    if(ticketOfNumber * 5 > tenOfNumber * 10) {
                        System.out.println("钱不够买票");
                        lock.unlock();
                        return;
                    } else {
                        if(ticketOfNumber % 2 == 0) {
                            System.out.print("客户原有" + tenOfNumber + "张10元," + ",买票总钱数是:" + (ticketOfNumber * 5));
                            tenOfNumber -= ticketOfNumber / 2;
                            tenOfNum += ticketOfNumber / 2;
                            System.out.println(", 客户现有" + fiveOfNumber + "张5元" + ", 客户现有" + tenOfNumber + "张10元"
                                    + ", 客户现有" + twentyOfNumber + "张20元" + " 不用找零,现在售货员剩余五元:" + fiveOfNum + "张"
                                    + " 、十元: " + tenOfNum + "张" + " 、 二十元: " + twentyOfNum + "张");
                            condition.signalAll();
                        } else {
                            //买奇数张票,有一张需要找零
                            if(fiveOfNum <= 0) {
                                System.out.println("要找零一张五元钱,但是没有,线程睡眠");
                                //Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
                                condition.await();
                                //Thread.sleep(5);
                                System.out.print(name + " ");
                            }
                            if(!(fiveOfNum <= 0)) {
                                System.out.print("客户原有" + tenOfNumber + "张10元," + ",买票总钱数是: " + (ticketOfNumber * 5));
                                fiveOfNum--;
                                fiveOfNumber++;
                                tenOfNum += (ticketOfNumber + 1) / 2;
                                tenOfNumber -= (ticketOfNumber + 1) / 2;
                                System.out.println(", 客户现有" + fiveOfNumber + "张5元" + ", 客户现有" + tenOfNumber + "张10元"
                                        + ", 客户现有" + twentyOfNumber + "张20元" + " 找零5元,现在售货员剩余五元:" + fiveOfNum + "张"
                                        + " 、十元: " + tenOfNum + "张" + " 、 二十元: " + twentyOfNum + "张");
                                condition.signalAll();
                            }
                        }
                    }
                } else if(fiveOfNumber == 0 && tenOfNumber == 0 && twentyOfNumber != 0) {
                    if(ticketOfNumber * 5 > twentyOfNumber * 20) {
                        System.out.println("钱不够买票");
                        lock.unlock();
                        return;
                    } else {
                        if(ticketOfNumber % 2 == 0) {
                            if(ticketOfNumber >= 4 && ticketOfNumber % 4 == 0) {
                                //4的倍数
                                System.out.print("客户原有" + twentyOfNumber + "张20元," + ",买票总钱数是: " + (ticketOfNumber * 5));
                                twentyOfNumber -= ticketOfNumber / 4;
                                twentyOfNum += ticketOfNumber / 4;
                                System.out.println(", 客户现有" + fiveOfNumber + "张5元" + ", 客户现有" + tenOfNumber + "张10元"
                                        + ", 客户现有" + twentyOfNumber + "张20元" + " 不用找零,现在售货员剩余五元:" + fiveOfNum + "张"
                                        + " 、十元: " + tenOfNum + "张" + " 、 二十元: " + twentyOfNum + "张");
                                condition.signalAll();
                            } else {
                                //只是2的倍数,不是4的倍数,找一张10元零钱
                                //2、6、10、14、
                                System.out.print("客户原有" + twentyOfNumber + "张20元," + ",买票总钱数是: " + (ticketOfNumber * 5));
                                if(tenOfNum <= 0) {
                                    System.out.println("要找零一张十元钱,但是没有,线程睡眠");
                                    //Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
                                    condition.await();
                                    //Thread.sleep(5);
                                    System.out.print(name + " ");
                                }
                                if(!(tenOfNum <= 0)) {
                                    tenOfNum--;
                                    tenOfNumber++;
                                    twentyOfNum += (ticketOfNumber + 2) / 4;
                                    twentyOfNumber -= (ticketOfNumber + 2) / 4;
                                    System.out.print("客户原有" + twentyOfNumber + "张20元," + ",买票总钱数是: " + (ticketOfNumber * 5));
                                    System.out.println(", 客户现有" + fiveOfNumber + "张5元" + ", 客户现有" + tenOfNumber + "张10元"
                                            + ", 客户现有" + twentyOfNumber + "张20元" + " ,要找零10元,现在售货员剩余五元:" + fiveOfNum + "张"
                                            + " 、十元: " + tenOfNum + "张" + " 、 二十元: " + twentyOfNum + "张");
                                    condition.signalAll();
                                }
                            }
                        } else {
                            //不是2的倍数的时候
                            if((ticketOfNumber - 1) % 4 == 0) {
                                //1、5、9、、、、、
                                if(tenOfNum <= 0 || fiveOfNum <= 0) {
                                    System.out.println("要找零一张五元钱和一张十元钱,但是没有,线程睡眠");
                                    //Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
                                    condition.await();
                                    //Thread.sleep(5);
                                    System.out.print(name + " ");
                                }
                                if(!(tenOfNum <= 0 || fiveOfNum <= 0)) {
                                    System.out.print("客户原有" + twentyOfNumber + "张20元," + ",买票总钱数是: " + (ticketOfNumber * 5));
                                    fiveOfNum--;
                                    fiveOfNumber++;
                                    tenOfNum--;
                                    tenOfNumber++;
                                    twentyOfNumber -= (ticketOfNumber / 4 + 1);
                                    twentyOfNum += (ticketOfNumber / 4 + 1);
                                    System.out.println(", 客户现有" + fiveOfNumber + "张5元" + ", 客户现有" + tenOfNumber + "张10元"
                                            + ", 客户现有" + twentyOfNumber + "张20元" + " ,要找零一张10元和一张五元,现在售货员剩余五元:" + fiveOfNum + "张"
                                            + " 、十元: " + tenOfNum + "张" + " 、 二十元: " + twentyOfNum + "张");
                                    condition.signalAll();
                                }
                            } else if((ticketOfNumber + 1) % 4 == 0) {
                                //3、7、11、、、、、
                                if(fiveOfNum <= 0) {
                                    System.out.println("要找零一张五元钱,但是没有,线程睡眠");
                                    //Thread.currentThread().setPriority(Thread.MAX_PRIORITY);
                                    condition.await();
                                    //Thread.sleep(5);
                                    System.out.print(name + " ");
                                }
                                if(!(fiveOfNum <= 0)) {
                                    System.out.print("客户原有" + twentyOfNumber + "张20元," + ",买票总钱数是: " + (ticketOfNumber * 5));
                                    fiveOfNum--;
                                    fiveOfNumber++;
                                    twentyOfNumber -= (ticketOfNumber / 4 + 1);
                                    twentyOfNum += (ticketOfNumber / 4 + 1);
                                    System.out.println(", 客户现有" + fiveOfNumber + "张5元" + ", 客户现有" + tenOfNumber + "张10元"
                                            + ", 客户现有" + twentyOfNumber + "张20元" + " ,要找零一张五元,现在售货员剩余五元:" + fiveOfNum + "张"
                                            + " 、十元: " + tenOfNum + "张" + " 、 二十元: " + twentyOfNum + "张");
                                    condition.signalAll();
                                }
                            }
                        }
                    }
                }
                lock.unlock();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
    }

    }

    class TicketSeller{
        public static void main(String[] args) {
            Money money = new Money(true);


        /*new Buy(money, 0, 4, 0,3,"1号").start();
        new Buy(money, 0, 0, 1,3,"2号").start();
        new Buy(money, 0, 0, 1,1,"3号").start();
        new Buy(money, 0, 1, 0,2,"4号").start();
        new Buy(money, 0, 3, 0,4,"5号").start();
        new Buy(money, 3, 0, 0,3,"6号").start();
        new Buy(money, 3, 0, 0,4,"7号").start();
        new Buy(money, 0, 0, 2,4,"8号").start();
        new Buy(money, 0, 0, 2,8,"9号").start();
        new Buy(money, 0, 0, 2,7,"10号").start();*/


            new Buy(money, 0, 0, 1,2,"赵").start();
            new Buy(money, 0, 0, 1,1,"钱").start();
            new Buy(money, 0, 1, 0,1,"孙").start();
            new Buy(money, 0, 1, 0,2,"李").start();
            new Buy(money, 1, 0, 0,1,"周").start();
        }
    }

3、最终版(暂定为最终版)解决了排序问题。。。。仅仅只是在公平锁的前提下,加入sleep,start一个sleep一会儿,貌似解决了排序问题

在这里插入图片描述

感觉是赵钱都被阻塞,阻塞队列里赵在前,所以当一旦满足条件,赵先“解封”,而即使之前已经满足“解封”钱的条件,也要先等赵,参考下面的23号也是这样

在这里插入图片描述

package Ex4.Thirdquestion;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * @author 15328
 * *3、编写Java应用程序模拟5个人排队买票。
 * 售票员只有1张五元的钱,电影票五元钱一张。
 * 假设5个人的名字及排队顺序是:赵、钱、孙、李、周。
 * “赵”拿1张二十元的人民币买2张票,
 * “钱”拿1张二十元的人民币买1张票,
 * “孙”1张十元的人民币买1张票,
 * “李”拿1张十元的人民币买2张票,
 * “周”拿1张五元的人民币买1张票。
 * 要求售票员按如下规则找赎:
 * (1)二十元买1张票,找零:1张十元;不许找零2张五元。
 * (2)二十元买1张票,找零:1张十元,1张五元;不许找零3张五元。
 * (3)十元买一张票,找零1张五元。
 */
public class Buy extends Thread {

    Money money;

    private  int fiveOfNumber;
    private  int tenOfNumber;
    private  int twentyOfNumber;
    private int ticketOfNum;
    private String name;
    public Buy(Money money,int fiveOfNumber, int tenOfNumber, int twentyOfNumber,int ticketOfNum,String name) {
        this.fiveOfNumber = fiveOfNumber;
        this.tenOfNumber = tenOfNumber;
        this.twentyOfNumber = twentyOfNumber;
        this.ticketOfNum = ticketOfNum;
        this.money = money;
        this.name = name;
        Thread.currentThread().setName(this.name);
    }


    @Override
    public void run() {
        Thread.currentThread().setName(this.name);
        money.givechange(fiveOfNumber,tenOfNumber,twentyOfNumber,ticketOfNum,Thread.currentThread().getName());
    }
}




class Money {
    private static int fiveOfNum = 1;
    private static int tenOfNum = 0;
    private static int twentyOfNum = 0;

    public Lock lock;
    public Condition condition;
    public Money(boolean fair){
        lock = new ReentrantLock(fair);
        condition = lock.newCondition();
    }


    public void givechange1(int fiveOfNumber, int tenOfNumber, int twentyOfNumber, int ticketOfNumber, String name) {
        System.out.print("客户原有" + fiveOfNumber + "张5元," + ",买票总钱数是:" + (ticketOfNumber * 5));
        fiveOfNumber -= ticketOfNumber;
        fiveOfNum += ticketOfNumber;
        System.out.println(", 客户现有" + fiveOfNumber + "张5元" + ", 客户现有" + tenOfNumber + "张10元"
                + ", 客户现有" + twentyOfNumber + "张20元" + " 不用找零,现在售货员剩余五元:" + fiveOfNum + "张"
                + " 、十元: " + tenOfNum + "张" + " 、 二十元: " + twentyOfNum + "张");
        condition.signalAll();
}

    public void givechange2(int fiveOfNumber, int tenOfNumber, int twentyOfNumber, int ticketOfNumber, String name) throws InterruptedException {
        if(ticketOfNumber % 2 == 0) {
            System.out.print("客户原有" + tenOfNumber + "张10元," + ",买票总钱数是:" + (ticketOfNumber * 5));
            tenOfNumber -= ticketOfNumber / 2;
            tenOfNum += ticketOfNumber / 2;
            System.out.println(", 客户现有" + fiveOfNumber + "张5元" + ", 客户现有" + tenOfNumber + "张10元"
                    + ", 客户现有" + twentyOfNumber + "张20元" + " 不用找零,现在售货员剩余五元:" + fiveOfNum + "张"
                    + " 、十元: " + tenOfNum + "张" + " 、 二十元: " + twentyOfNum + "张");
        } else {
            //买奇数张票,有一张需要找零
            if(fiveOfNum <= 0) {
                System.out.println("要找零一张五元钱,但是没有,线程睡眠");
                condition.await();
                System.out.print(name + " ");
            }
            if(!(fiveOfNum <= 0)) {
                System.out.print("客户原有" + tenOfNumber + "张10元," + ",买票总钱数是: " + (ticketOfNumber * 5));
                fiveOfNum--;
                fiveOfNumber++;
                tenOfNum += (ticketOfNumber + 1) / 2;
                tenOfNumber -= (ticketOfNumber + 1) / 2;
                System.out.println(", 客户现有" + fiveOfNumber + "张5元" + ", 客户现有" + tenOfNumber + "张10元"
                        + ", 客户现有" + twentyOfNumber + "张20元" + " 找零5元,现在售货员剩余五元:" + fiveOfNum + "张"
                        + " 、十元: " + tenOfNum + "张" + " 、 二十元: " + twentyOfNum + "张");
            }
        }
    }
    public void givechange3(int fiveOfNumber, int tenOfNumber, int twentyOfNumber, int ticketOfNumber, String name) throws InterruptedException {
        if(ticketOfNumber % 2 == 0) {
            if(ticketOfNumber >= 4 && ticketOfNumber % 4 == 0) {
                //4的倍数
                System.out.print("客户原有" + twentyOfNumber + "张20元," + ",买票总钱数是: " + (ticketOfNumber * 5));
                twentyOfNumber -= ticketOfNumber / 4;
                twentyOfNum += ticketOfNumber / 4;
                System.out.println(", 客户现有" + fiveOfNumber + "张5元" + ", 客户现有" + tenOfNumber + "张10元"
                        + ", 客户现有" + twentyOfNumber + "张20元" + " 不用找零,现在售货员剩余五元:" + fiveOfNum + "张"
                        + " 、十元: " + tenOfNum + "张" + " 、 二十元: " + twentyOfNum + "张");
                condition.signalAll();
            } else {
                //只是2的倍数,不是4的倍数,找一张10元零钱
                //2、6、10、14、
                System.out.print("客户原有" + twentyOfNumber + "张20元," + ",买票总钱数是: " + (ticketOfNumber * 5));
                if(tenOfNum <= 0) {
                    System.out.println("要找零一张十元钱,但是没有,线程睡眠");
                    condition.await();
                    System.out.print(name + " ");
                }
                if(!(tenOfNum <= 0)) {
                    tenOfNum--;
                    tenOfNumber++;
                    twentyOfNum += (ticketOfNumber + 2) / 4;
                    twentyOfNumber -= (ticketOfNumber + 2) / 4;
                    System.out.print("客户原有" + twentyOfNumber + "张20元," + ",买票总钱数是: " + (ticketOfNumber * 5));
                    System.out.println(", 客户现有" + fiveOfNumber + "张5元" + ", 客户现有" + tenOfNumber + "张10元" + ", 客户现有" + twentyOfNumber + "张20元" + " ,要找零10元,现在售货员剩余五元:" + fiveOfNum + "张"
                            + " 、十元: " + tenOfNum + "张" + " 、 二十元: " + twentyOfNum + "张");
                    condition.signalAll();
                }
            }
        } else {
            //不是2的倍数的时候
            if((ticketOfNumber - 1) % 4 == 0) {
                //1、5、9、、、、、
                if(tenOfNum <= 0 || fiveOfNum <= 0) {
                    System.out.println("要找零一张五元钱和一张十元钱,但是没有,线程睡眠");
                    condition.await();
                    System.out.print(name + " ");
                }
                if(!(tenOfNum <= 0 || fiveOfNum <= 0)) {
                    System.out.print("客户原有" + twentyOfNumber + "张20元," + ",买票总钱数是: " + (ticketOfNumber * 5));
                    fiveOfNum--;
                    fiveOfNumber++;
                    tenOfNum--;
                    tenOfNumber++;
                    twentyOfNumber -= (ticketOfNumber / 4 + 1);
                    twentyOfNum += (ticketOfNumber / 4 + 1);
                    System.out.println(", 客户现有" + fiveOfNumber + "张5元" + ", 客户现有" + tenOfNumber + "张10元"
                            + ", 客户现有" + twentyOfNumber + "张20元" + " ,要找零一张10元和一张五元,现在售货员剩余五元:" + fiveOfNum + "张"
                            + " 、十元: " + tenOfNum + "张" + " 、 二十元: " + twentyOfNum + "张");
                    condition.signalAll();
                }
            } else if((ticketOfNumber + 1) % 4 == 0) {
                //3、7、11、、、、、
                if(fiveOfNum <= 0) {
                    System.out.println("要找零一张五元钱,但是没有,线程睡眠");
                    condition.await();
                    System.out.print(name + " ");
                }
                if(!(fiveOfNum <= 0)) {
                    System.out.print("客户原有" + twentyOfNumber + "张20元," + ",买票总钱数是: " + (ticketOfNumber * 5));
                    fiveOfNum--;
                    fiveOfNumber++;
                    twentyOfNumber -= (ticketOfNumber / 4 + 1);
                    twentyOfNum += (ticketOfNumber / 4 + 1);
                    System.out.println(", 客户现有" + fiveOfNumber + "张5元" + ", 客户现有" + tenOfNumber + "张10元"
                            + ", 客户现有" + twentyOfNumber + "张20元" + " ,要找零一张五元,现在售货员剩余五元:" + fiveOfNum + "张"
                            + " 、十元: " + tenOfNum + "张" + " 、 二十元: " + twentyOfNum + "张");
                    condition.signalAll();
                }
            }
        }
    }


    public void givechange(int fiveOfNumber,int tenOfNumber,int twentyOfNumber,int ticketOfNumber,String name)  {
        try {
            lock.lock();
            System.out.print(name + " ");
            if(fiveOfNumber != 0 && tenOfNumber == 0 && twentyOfNumber == 0) {
                if(ticketOfNumber > fiveOfNumber) {
                    System.out.println("钱不够买票");
                    return;
                } else {
                    givechange1(fiveOfNumber, tenOfNumber, twentyOfNumber, ticketOfNumber, name);
                }
            } else if(fiveOfNumber == 0 && tenOfNumber != 0 && twentyOfNumber == 0) {
                if(ticketOfNumber * 5 > tenOfNumber * 10) {
                    System.out.println("钱不够买票");
                    return;
                } else {
                    givechange2(fiveOfNumber, tenOfNumber, twentyOfNumber, ticketOfNumber, name);
                }
            } else if(fiveOfNumber == 0 && tenOfNumber == 0 && twentyOfNumber != 0) {
                if(ticketOfNumber * 5 > twentyOfNumber * 20) {
                    System.out.println("钱不够买票");
                    return;
                } else {
                    givechange3(fiveOfNumber, tenOfNumber, twentyOfNumber, ticketOfNumber, name);
                }
            } else {
                System.out.println("非法输入");
            }
        } catch (InterruptedException interruptedException) {
            interruptedException.printStackTrace();
        } finally {
            lock.unlock();
        }
    }
}

class TicketSeller{
    public static void main(String[] args) throws InterruptedException {
        Money money = new Money(true);


        /*new Buy(money, 0, 4, 0,3,"1号").start();
        Thread.sleep(100);
        new Buy(money, 0, 0, 1,3,"2号").start();
        Thread.sleep(100);
        new Buy(money, 0, 0, 1,1,"3号").start();
        Thread.sleep(100);
        new Buy(money, 0, 1, 0,2,"4号").start();
        Thread.sleep(100);
        new Buy(money, 0, 3, 0,4,"5号").start();
        Thread.sleep(100);
        new Buy(money, 3, 0, 0,3,"6号").start();
        Thread.sleep(100);
        new Buy(money, 3, 0, 0,4,"7号").start();
        Thread.sleep(100);
        new Buy(money, 0, 0, 2,4,"8号").start();
        Thread.sleep(100);
        new Buy(money, 0, 0, 2,8,"9号").start();
        Thread.sleep(100);
        new Buy(money, 0, 0, 2,7,"10号").start();
        Thread.sleep(100);*/

        Buy [] buys = new Buy[5];
        buys [0] = new Buy(money, 0, 0, 1,2,"赵");
        buys[0].setName("赵");
        buys [1] = new Buy(money, 0, 0, 1,1,"钱");
        buys[1].setName("钱");
        buys [2] = new Buy(money, 0, 1, 0,1,"孙");
        buys[2].setName("孙");
        buys [3] = new Buy(money, 0, 1, 0,2,"李");
        buys[3].setName("李");
        buys [4] = new Buy(money, 1, 0, 0,1,"周");
        buys[4].setName("周");

        for(int i = 0; i < 5; i++) {
            buys[i].start();
            Thread.sleep(100);
        }
    }
}


  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值