import java.util.Date;
public class chap8_5 
{
static sale ssss=new sale(6,0,0);
static Date date=new Date();
  public static void main(String s[])
  {
 int n[]={10,10,5,10,5,5}; 
 Thread t[]=new Thread[10];
 
 for(int i=0;i<6;i++)
 {
 t[i]=new Thread(new custom(i+1,n[i],ssss));
 t[i].start();
 }
 loop:
 while(true)
 {
 for(int m=0;m<6;m++)
 {
if( t[m].isAlive()) continue loop;
 }
 break;
 }
// (Long)(date.getTime())

 System.out.println(Integer .toString(date.getHours())+":"+Integer .toString(date.getMinutes())+":"+Integer .toString(date.getSeconds())+" 购票结束");
  }
}
class sale
{
int memontoes,five,ten;
Date date=new Date();
sale(int m,int f,int t)
{
memontoes=m;
five=f;
ten=t;
}
synchronized String salef(int num,int money)
{
String s=null;
int seconds = date.getSeconds();
if(memontoes<=0)
{
s="没有票了,对不起。 ";
return s;
}
if(money==5)
{
//System.out.println("*******");
memontoes--;
five++;
// System.out.println("-----");
s="给您票,钱正好。五元:"+five+"  十元:"+ten;
//notify();

}
else if(money==10)
{
if(five<1)
//while()
{
System.out.println("我是第"+num+"个顾客,售货员说:没有零钱,请等待。");
try{wait();}catch(InterruptedException e){}
}
five--;
ten++;
memontoes--;

s="给您票,你给我10元,找您5元。五元:"+five+"  十元:"+ten;
}
if(five>0)
//System.out.println(num+" notify ");

notify();
return s;
}
}
class custom implements Runnable
{
sale sa;
    int num,money;
    custom(int n,int m,sale s)
    {
     num=n;
     money=m;
     sa=s;
    }
    public void goumai()
    {
       System.out.println("我是第"+num+"个顾客,售货员说:"+sa.salef(num, money));
    
    }
public void run() 
{
// TODO Auto-generated method stub
try
{
Thread.sleep(1000);
}
catch(InterruptedException e)
{

}
 goumai();

}

}
输出结果:
我是第1个顾客,售货员说:没有零钱,请等待。
我是第2个顾客,售货员说:没有零钱,请等待。
我是第4个顾客,售货员说:没有零钱,请等待。
我是第6个顾客,售货员说:给您票,钱正好。五元:1  十元:0
我是第1个顾客,售货员说:给您票,你给我10元,找您5元。五元:0  十元:1
我是第2个顾客,售货员说:给您票,你给我10元,找您5元。五元:0  十元:2
我是第3个顾客,售货员说:给您票,钱正好。五元:1  十元:1
我是第4个顾客,售货员说:给您票,你给我10元,找您5元。五元:0  十元:3
我是第5个顾客,售货员说:给您票,钱正好。五元:1  十元:2
21:45:16 购票结束
怎么结果和我越想的不一样呀,哪里出了问题?
我这个题目,顾客购买车票,车票每张5元,顾客使用的货币面额为5元和10元。顾客购买车票时,如果没有5元的,顾客只能等待。
不知道说明白了吗?

解决方案 »

  1.   

    你的电脑是双核的吧
    双核的电脑运行生产者消费者问题的java程序是和单核的不一样
      

  2.   

    个人认为:楼主如果仍将此程序运行几次,出现的结果会不一样!这是由于线程的不确定性造成的!
    因为当你用循环启动6个线程后,假若一号线程抢到了CPU资源,它运行休眠完1秒之后,其他5个线程便“虎视”着CPU资源,也就是说,在1号线程休眠完之后,2--6号线程都是有机会抢到CPU资源的。虽然你贴出来的程序1号和2号的顺序都比较碰巧。但紧接着并未出现3号线程而是4号线程,再次验证了线程在同等优先级的情况下,能够相互抢夺执行机会!而楼主的意思,如果我没有猜错的话,你是想实现如下步骤:
    ======================================
    你定义了int n[]={10,10,5,10,5,5}; 是想说明6个顾客的持币情况吧?如果以你的程序                                收银员持币情况:
    =======================第一轮
    我是第一个,收银员说没钱,请等
    我是第二个,收银员说没钱,请等
    我是第三个,收银员说钱正好        5:1
    我是第四个,收银员说找5元         5:0   10:1
    我是第五个,收银员说钱正好        5:1 10:1
    我是第六个,收银员说钱正好        5:2 10:1
    -----------------------------
    此时1,2号顾客线程休息一秒之后就“死了”,等待下一次复活[你在主程序中有控制,不过对你使用loop方式来控制的方法实在是不敢苟同(loop关键字是高级语言编程的一大禁忌)]
    ======================第二轮
    我是第一个,给10元,回5元。        5:1 10:2
    我是第二个,给10元,回5元         5:2 10:2购票结束!
    ========================
    综上所述,我想给楼主的建议就是:
    建立一个线程队列,以保证线程按其序号顺序执行,未购买成功的再将其放入该队列中,循环读取队列,直至队列长度为0结束!    
      

  3.   

    非常感谢,我现在正在学习java,这是书上的一个例子。所以只是为了弄明白他的原理。当然我也不要求顾客来的顺序一定是一定是1 2 3 4 5 6顺序到来。楼上说的很对,每次运行都有不同的结果,这是因为多个线程运行的不确定性,但是对于有的结果,比如说,我贴出来的那个结果,我就不明白怎么运行出来的。以我结过为例:前三个为10元顾客,由于wait()进入等待状态,第四个顾客为5元顾客,这是调用一次notify(),可以唤醒一个10元顾客,为什么这时候能唤醒了2个10元顾客?请教。主要想弄明白这里面的原因
      

  4.   

    我是第1个顾客,售货员说:没有零钱,请等待。 
    我是第2个顾客,售货员说:没有零钱,请等待。 
    我是第4个顾客,售货员说:没有零钱,请等待。 
    我是第6个顾客,售货员说:给您票,钱正好。五元:1  十元:0 
    我是第1个顾客,售货员说:给您票,你给我10元,找您5元。五元:0  十元:1 
    我是第2个顾客,售货员说:给您票,你给我10元,找您5元。五元:0  十元:2 
    我是第3个顾客,售货员说:给您票,钱正好。五元:1  十元:1 
    我是第4个顾客,售货员说:给您票,你给我10元,找您5元。五元:0  十元:3 
    我是第5个顾客,售货员说:给您票,钱正好。五元:1  十元:2 
    =============================================
    其实6线程执行时,虽然你人为的在synchronized String salef(int num,int money) 方法中进行线程唤醒,这时也确实唤醒了一个(至于哪一个,由JVM决定),但JVM比较聪明,它不希望因为自己的原因造成程序死锁。又因为wait和notify/notifyall方法都是在synchronized 方法中才有效的。而线程的run方法也具有排它性(相当于一个synchronized方法)。所以6线程在执行完run方法之前,隐式调用notifyall唤醒另外2个之前wait过的线程!
      

  5.   

    6楼,我不是特明白你的意思,如果java 采用这种处理方式,不就失去了处理互斥同步问题的能力了。