今晚在csdn上乱逛,随便点了一些推荐的帖子,看到一个模拟多人售票的程序,然后看了下各位高手的作答,再自己动手写了下。总算完工,但是出现了些莫名的错误,找了很久也没找到问题!现将代码贴上,各位帮忙指出错误!/**
 * @(#)SellTicket.java
 *
 *
 * @author
 * @version 1.00 2010/8/21
 */class SellLady{
int tickCount,five,ten ; //票数,5元零钞,10元零钞
static int Priority = 10 ; //设置线程优先级,越早等待值越大
public SellLady(int count,int five,int ten){
this.tickCount = count ;
this.five = five ;
this.ten = ten ;
}
   public synchronized  static int getPriority(){
      SellLady.Priority--;
      if(SellLady.Priority <0)
        SellLady.Priority = 0 ;
        return SellLady.Priority;
    }
public synchronized  String sell(int num ,int money){
String msg = "" ;
if(tickCount <= 0)
  return "对不起,票已售完,明天请早!" ;
        else if(money == 5){
         tickCount--;
         five++;
         msg = "给你票,你的钱正好,不用找零!" +five;
         notifyAll();
        }else if(money ==10){
         while(five < 1){
          try {
           System.out.println("" + num + "号顾客用10元购票,请等待 " +five);
             //   Thread.currentThread().setPriority(SellLady.getPriority()) ;
           wait();               } catch (InterruptedException e) {}         }
         //二次判断
        if(tickCount <= 0) return "对不起,票已售完,明天请早!" ;
        tickCount--;
        five--;
        ten++;
        msg = "给你票,找你5元。" +five;
        }
         return msg ;
}
}class Buyer implements Runnable{
    int num ,money ;
    public Buyer(int n,int m){
     this.num = n ;
     this.money = m;
    }    public void run(){
    // synchronized(this){
     System.out.println("我是"+num+"号顾客,用"+money+"元钱买票,售票员说:"+SellTicket.sl.sell(num,money));
   //   }
    }
}
public class SellTicket {    public SellTicket() {
    }   static SellLady sl = new SellLady(14,0,0);
   public static void main (String[] args) {     Buyer[] by = new Buyer[14] ;                                         //14位顾客,对应14张票
     int[] money ={ 10, 10, 5, 10, 5, 10, 5, 5, 10, 5, 10, 5, 5, 10}; //对应14位顾客买票的币值
     Thread[] t = new Thread[14] ;
     for(int i=0;i<by.length;i++){
by[i] = new Buyer(i+1,money[i]);
    t[i]  = new Thread(by[i]) ;
    t[i].start();
     }     for (int i = 0; i < by.length; i++) {
      try {
        t[i].join();
      } catch (InterruptedException e) {
        e.printStackTrace();
      }
    }
    System.out.println("票已售完" +sl.tickCount);
  }}
再附上某次的运行结果:
1号顾客用10元购票,请等待 0
我是3号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!1
1号顾客用10元购票,请等待 0
我是2号顾客,用10元钱买票,售票员说:给你票,找你5元。0
4号顾客用10元购票,请等待 0
我是5号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!1
1号顾客用10元购票,请等待 0
我是4号顾客,用10元钱买票,售票员说:给你票,找你5元。0
我是7号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!1
我是6号顾客,用10元钱买票,售票员说:给你票,找你5元。0
9号顾客用10元购票氲却?0
1号顾客用10元购票,请等待 0
我是8号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!1
9号顾客用10元购票,请等待 0
我是1号顾客,用10元钱买票,售票员说:给你票,找你5元。0
我是10号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!1
我是11号顾客,用10元钱买票,售票员说:给你票,找你5元。0
9号顾客用10元购票,请等待 0
我是9号顾客,用10元钱买票,售票员说:给你票,找你5元。0
我是12号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!1
我是13号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!1
我是14号顾客,用10元钱买票,售票员说:给你票,找你5元。0
票已售完0
-----------------------------------------------------------------
一些说明:
程序里有14个进程,模拟14个顾客买票,对应有个数组存放买票的币值。若是5元,还剩票,直接可以买;若是10元,还剩票,则需要有5元零钞才可以买!

解决方案 »

  1.   

        public synchronized  String sell(int num ,int money){
            String msg = "" ;
            if(tickCount <= 0)
              return "对不起,票已售完,明天请早!" ;
            else if(money == 5){
                tickCount--;
                five++;
                msg = "给你票,你的钱正好,不用找零!" +five;
                notifyAll();
            }else if(money ==10){
                while(five < 1){
                     try {
                          System.out.println("" + num + "号顾客用10元购票,请等待 " +five);
                    //      Thread.currentThread().setPriority(SellLady.getPriority()) ;
                          wait();                  } catch (InterruptedException e) {}            }
                //二次判断
    上面红色的你换成 ++five; 试一下
      

  2.   


    试了,还是不行~~~~~~~~~
    另外说下,那个乱码应该是和环境有关!因为我是在JC下运行的,运行多几次就会出现乱码了。但是我转到cmd下去运行,无论运行多少次都不会出现乱码~~~~~
      

  3.   

    倒回去翻了下书,看下 ++ 运算符!
    在这里 five++ 和 ++five 都一样,因为five值都会自增1。
    只有在赋值给其他变量的时候,这2者才会有不同。比如:
    b = five++ ;
    b = ++five ;
    第一种是先赋值再运算。结果b=five
    第二种是先运算再赋值,结果是b=five+1 ;
    当复习了~~~~~~
      

  4.   

    测试了下,发现没什么特别问题。估计是因为打印的关系,造成紊乱了
    如果所有打印都放在同步块内,就没有问题了附带修改后的代码/**
     * @(#)SellTicket.java
     * @author
     * @version 1.00 2010/8/21
     */class SellLady {
    int tickCount, five, ten; // 票数,5元零钞,10元零钞
    static int Priority = 10; // 设置线程优先级,越早等待值越大 public SellLady(int count, int five, int ten) {
    this.tickCount = count;
    this.five = five;
    this.ten = ten;
    } public synchronized static int getPriority() {
    SellLady.Priority--;
    if (SellLady.Priority < 0)
    SellLady.Priority = 0;
    return SellLady.Priority;
    } private void println(String s) {
    Buyer b = (Buyer) Thread.currentThread();
    System.out.println("售票员:你好," + b.num + "号顾客," + s);
    } public synchronized void sell(int num, int money) {
    System.out.println(num + "号顾客:用" + money + "元买票");
    if (tickCount <= 0) {
    println("对不起,票已售完,明天请早!");
    return;
    } else if (money == 5) {
    tickCount--;
    five++;
    println("给你票,你的钱正好,不用找零!");
    System.out.println("售票员:5元零钞还有" + five + "张");
    notifyAll();
    } else if (money == 10) {
    if (five < 1)
    println("无5元零钞,请等待!");
    while (five < 1) {
    System.out.println(num + "号顾客:我等....");
    try {
    wait();
    } catch (InterruptedException ie) {
    break;
    }
    }
    // 二次判断
    if (tickCount <= 0)
    println("对不起,票已售完,明天请早!");
    else {
    tickCount--;
    five--;
    ten++;
    println("给你票,找你5元。");
    System.out.println("售票员:5元零钞还有" + five + "张");
    }
    }
    }
    }class Buyer extends Thread {
    int num, money; public Buyer(int n, int m) {
    this.num = n;
    this.money = m;
    } public void run() {
    SellTicket.sl.sell(num, money);
    }
    }public class SellTicket { public SellTicket() {
    } static SellLady sl = new SellLady(14, 0, 0); public static void main(String[] args) {
    Buyer[] by = new Buyer[14]; // 14位顾客,对应14张票
    int[] money = { 10, 10, 5, 10, 5, 10, 5, 5, 10, 5, 10, 5, 5, 10 }; // 对应14位顾客买票的币值
    for (int i = 0; i < by.length; i++) {
    by[i] = new Buyer(i + 1, money[i]);
    by[i].start();
    } for (int i = 0; i < by.length; i++) {
    try {
    by[i].join();
    } catch (InterruptedException e) {
    e.printStackTrace();
    }
    }
    System.out.println("票已售完" + sl.tickCount);
    }
    }
      

  5.   

    虽然调通了,但是还是有些地方不明白!请LS的指点下!
    为什么直接打印出来就会顺序紊乱,而你修改后的代码也就是加了个打印的方法,但是这个方法都没使用synchronized,为什么酒不会顺序紊乱呢?!请指点,谢谢
      

  6.   

    呵呵,刚提交完上面的回复后就晃过神来了,呵呵,明白是怎么回事。
    把打印操作都放在了同步的方法里面,就没问题了!
    但是我之前测试的时候,
    把下面的2行注释去掉,也是打印混乱,难道我加的synchronized没有用?!请教原因...
     public void run(){
        //    synchronized(this){
            System.out.println("我是"+num+"号顾客,用"+money+"元钱买票,售票员说:"+SellTicket.sl.sell(num,money));
       //   }
    谢谢不厌其烦的指点,谢谢~~~~~~~~~
      

  7.   

    你锁住的是当前的一个Buyer对象实例(实际上是个线程),没有锁住大家(Buyer线程)能访问的那块公有资源SellLady(所以程序一定只能有一个sl),你锁住那个线程没有任何意义,更不用说保证打印同步了,待会给你写具体实现代码~~
      

  8.   

    如果不要求排队,没有先来后到一说的话(就是14个线程的优先级一样):class SellLady{
        int tickCount,five,ten ; //票数,5元零钞,10元零钞
        
        public SellLady(int count,int five,int ten){
            this.tickCount = count ;
            this.five = five ;
            this.ten = ten ;
        }
     
        
        public synchronized  void sell(int num ,int money) {
            if(tickCount <= 0) {
              System.out.println("我是"+num+"号顾客,用"+money+"元钱买票,售票员说:对不起,票已售完,明天请早!!("+five+")") ;
            }
            else if(money == 5){
                tickCount--;
                five++;
                System.out.println("我是"+num+"号顾客,用"+money+"元钱买票,售票员说:给你票,你的钱正好,不用找零!!("+five+")") ;
                notifyAll();
            }else if(money ==10){
                while(five < 1){
                     try {
                      System.out.println("我是"+num+"号顾客,用"+money+"元钱买票,售票员说:当前无法找退,请等待!!("+five+")") ;
                          wait();
                      } catch (InterruptedException e) {
                       e.printStackTrace();
                      }
                }
                //二次判断
            if(tickCount <= 0) {
             System.out.println("我是"+num+"号顾客,用"+money+"元钱买票,售票员说:对不起,票已售完,明天请早!!("+five+")");
            }
            tickCount--;
            five--;
            ten++;
            System.out.println("我是"+num+"号顾客,用"+money+"元钱买票,售票员说:给你票,找你5元!!("+five+")");
            }
        }
    }
    class Buyer implements Runnable{
        int num ,money ;
        public Buyer(int n,int m){
            this.num = n ;
            this.money = m;
        }    public void run(){
            SellTicket.sl.sell(num,money);
        }
    }
    public class SellTicket {
       static SellLady sl = new SellLady(14,0,0);
       
       public static void main (String[] args) {
        Buyer[] by = new Buyer[14] ;                                         //14位顾客,对应14张票
        int[] money ={ 10, 10, 5, 10, 5, 10, 5, 5, 10, 5, 10, 5, 5, 10}; //对应14位顾客买票的币值
        Thread[] t = new Thread[14] ;
        for(int i=0;i<by.length;i++){
                by[i] = new Buyer(i+1,money[i]);
                t[i]  = new Thread(by[i]) ;
                t[i].start();
             }
      }
    }测试结果:(每次执行的结果很有可能不一样,但都能保证刚好每人都可以买到一张)我是1号顾客,用10元钱买票,售票员说:当前无法找退,请等待!!(0)
    我是3号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!!(1)
    我是1号顾客,用10元钱买票,售票员说:给你票,找你5元!!(0)
    我是5号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!!(1)
    我是4号顾客,用10元钱买票,售票员说:给你票,找你5元!!(0)
    我是6号顾客,用10元钱买票,售票员说:当前无法找退,请等待!!(0)
    我是2号顾客,用10元钱买票,售票员说:当前无法找退,请等待!!(0)
    我是9号顾客,用10元钱买票,售票员说:当前无法找退,请等待!!(0)
    我是7号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!!(1)
    我是9号顾客,用10元钱买票,售票员说:给你票,找你5元!!(0)
    我是2号顾客,用10元钱买票,售票员说:当前无法找退,请等待!!(0)
    我是6号顾客,用10元钱买票,售票员说:当前无法找退,请等待!!(0)
    我是10号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!!(1)
    我是8号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!!(2)
    我是6号顾客,用10元钱买票,售票员说:给你票,找你5元!!(1)
    我是2号顾客,用10元钱买票,售票员说:给你票,找你5元!!(0)
    我是13号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!!(1)
    我是12号顾客,用5元钱买票,售票员说:给你票,你的钱正好,不用找零!!(2)
    我是14号顾客,用10元钱买票,售票员说:给你票,找你5元!!(1)
    我是11号顾客,用10元钱买票,售票员说:给你票,找你5元!!(0)
      

  9.   

    好了,总结下然后结贴!
    首先,程序逻辑什么的是没错的!之所以出现打印紊乱的原因在于:在
    class Buyer implements Runnable{
        int num ,money ;
        public Buyer(int n,int m){
            this.num = n ;
            this.money = m;
        }    public void run(){
        //    synchronized(this){
            System.out.println("我是"+num+"号顾客,用"+money+"元钱买票,售票员说:"+SellTicket.sl.sell(num,money));
       //   }
        }
    }
    在这个类里面我做了打印的操作。试想下,假如我同时启动了14个线程的话,那么我将无法确保打印的顺序!所以解决方法就是将打印的操作都放到同步方法sell里面,这样就能确保打印不会出现紊乱。感谢大家的指点。共同学习,共同进步!