多线程学习 - 简单的购票程序

废话不多说,直接上代码:

自定义的电影院

public class MyCinema{
    
    private int rest_tickets;//剩余票数
    private String name;//票名
    
    public MyCinema(String n,int r){
        this.rest_tickets = r;
        this.name = n;
        System.out.println(this.name +" 开始售票,还剩"+ this.rest_tickets+"张");
    }
    
    //购票,参数为客户名称和购票数量
    public synchronized void buyTicket(String n,int num){
        if(this.rest_tickets > 0){
            if(this.rest_tickets - num >=0){
                this.rest_tickets -= num;
                System.out.println(n+" 买了"+num+"张票,还剩"+this.rest_tickets+"张");
            }else{
                System.out.println(n+",还剩"+this.rest_tickets+"张票,不够购买"+num+"张,请重新购买");
            }
        }else{
            System.out.println("对不起,"+n+",票已售完");
        }
    }
}

自定义购买线程

public class BuyThread implements Runnable{
    private MyCinema mySale;//电影对象
    private String name;//买家姓名
    
    public BuyThread(MyCinema s,String n){
        this.mySale = s;
        this.name = n;
    }
    @Override
    public void run() {
        for (int i = 0; i < 2; i++) {
            try {
                Thread.sleep(200);//让线程休眠200ms,测试同步
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            mySale.buyTicket(this.name,(int)(Math.random()*2+1));//买票
        }
    }
}

测试类

public class Test {
    public static void main(String[] args) {
        //电影上映
        MyCinema mySale = new MyCinema("变形金刚", 10);
        //有客户不停的来买票,这里定义成售票窗口可能更合理
        BuyThread b1 = new BuyThread(mySale,"客户一");
        Thread t1 = new Thread(b1);
        BuyThread b2 = new BuyThread(mySale,"客户二");
        Thread t2 = new Thread(b2);
        BuyThread b3 = new BuyThread(mySale,"客户三");
        Thread t3 = new Thread(b3);
        BuyThread b4 = new BuyThread(mySale,"客户四");
        Thread t4 = new Thread(b4);
        BuyThread b5 = new BuyThread(mySale,"客户五");
        Thread t5 = new Thread(b5);
        //开始买票
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
    }
}

  测试结果:

      情况1                情况2

  变形金刚 开始售票,还剩10张    变形金刚 开始售票,还剩10张
  客户一 买了2张票,还剩8张     客户一 买了1张票,还剩9张
  客户二 买了1张票,还剩7张     客户二 买了1张票,还剩8张
  客户四 买了1张票,还剩6张     客户四 买了2张票,还剩6张
  客户三 买了1张票,还剩5张     客户五 买了1张票,还剩5张
  客户五 买了1张票,还剩4张     客户三 买了2张票,还剩3张
  客户二 买了1张票,还剩3张     客户一 买了2张票,还剩1张
  客户一 买了2张票,还剩1张     客户五,还剩1张票,不够购买2张,请重新购买
  客户三 买了1张票,还剩0张     客户二,还剩1张票,不够购买2张,请重新购买
  对不起,客户五,票已售完      客户四 买了1张票,还剩0张
  对不起,客户四,票已售完      对不起,客户三,票已售完

看来效果不错,不管怎么说他都成功了。

可是这样写有一个缺点,一共是五个客户,每个客户买两次,每次买一到两张,可是一共也就10张票,也就是说,如果前面每个人都买两张票的话,那第五次就卖光了,之后的客户就只能傻傻的去买,然后被售票小姐告知没票了,再抑郁的离开,这样显然对他们来说很不合理。此外,如果我这里一共不是10张票,而是20张甚至更多,则会出现卖不完的情况,这肯定是商家不愿意看到的,作为卖家,一定要坚持到最后一张票卖光为止。

 所以我重新修改了一下程序,新的程序中,客户会持续买票,直到卖完为止

先是电影院:

public class MyCinema{
    
    private int rest_tickets;//剩余票数
    private String name;//票名
    
    public MyCinema(String n,int r){
        this.rest_tickets = r;
        this.name = n;
        System.out.println(this.name +" 开始售票,还剩"+ this.rest_tickets+"张");
    }
    
    public int getRest_tickets() {
        return rest_tickets;
    }

    //购票,参数为客户名称和购票数量
    public synchronized void buyTicket(String n,int num){
        if(this.rest_tickets > 0){
            if(this.rest_tickets - num >=0){
                this.rest_tickets -= num;
                System.out.println(n+" 出售"+num+"张票,还剩"+this.rest_tickets+"张");
            }else{
                System.out.println(n+",还剩"+this.rest_tickets+"张票,不够出售"+num+"张,请下次再来");
            }
        }else{
            System.out.println("对不起,"+n+"票已售完");
            
        }
    }
}

然后是售票柜台:

public class BuyThread implements Runnable {
    private MyCinema mySale;// 电影对象
    private String name;// 买家姓名

    public BuyThread(MyCinema s, String n) {
        this.mySale = s;
        this.name = n;
    }

    private boolean isTicketsLeft() {
        return mySale.getRest_tickets() > 0;
    }

    @Override
    public void run() {
        while (isTicketsLeft()) {
            try {
                Thread.sleep(200);// 让线程休眠200ms,测试同步
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            if(isTicketsLeft()){
                mySale.buyTicket(this.name, (int) (Math.random() * 2 + 1));// 买票
            }
        }
        System.out.println("不好意思票卖完了," + this.name + ":(先生/小姐),请下次再来");
    }
}

测试类:

public class Test {
    public static void main(String[] args) {
        //电影上映
        MyCinema mySale = new MyCinema("变形金刚", 10);
        //有客户不停的来买票,这里定义成售票窗口可能更合理
        BuyThread b1 = new BuyThread(mySale,"窗口一");
        Thread t1 = new Thread(b1);
        BuyThread b2 = new BuyThread(mySale,"窗口二");
        Thread t2 = new Thread(b2);
        BuyThread b3 = new BuyThread(mySale,"窗口三");
        Thread t3 = new Thread(b3);
        BuyThread b4 = new BuyThread(mySale,"窗口四");
        Thread t4 = new Thread(b4);
        BuyThread b5 = new BuyThread(mySale,"窗口五");
        Thread t5 = new Thread(b5);
        //开始买票
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
    }
}

  测试结果:

  变形金刚 开始售票,还剩10张
  窗口四 出售2张票,还剩8张
  窗口一 出售1张票,还剩7张
  窗口二 出售1张票,还剩6张
  窗口三 出售2张票,还剩4张
  窗口五 出售1张票,还剩3张
  窗口四 出售1张票,还剩2张
  窗口三 出售1张票,还剩1张
  窗口二,还剩1张票,不够出售2张,请下次再来
  窗口一 出售1张票,还剩0张
  不好意思票卖完了,窗口一:(先生/小姐),请下次再来
  不好意思票卖完了,窗口五:(先生/小姐),请下次再来
  不好意思票卖完了,窗口四:(先生/小姐),请下次再来
  不好意思票卖完了,窗口二:(先生/小姐),请下次再来
  不好意思票卖完了,窗口三:(先生/小姐),请下次再来

  大概模拟出了想要的效果,有什么不对的地方再改进。

 

posted @ 2013-06-03 16:12  zydmayday  阅读(215)  评论(0编辑  收藏  举报