/*模仿三个售票窗口
   一个票类 
   一个存票类
   一个售票类
    那位好心人帮忙看看
*/
public class  Ex8_7a
{
public static void main(String[] args) 
    {
          Tickets t=new Tickets(10);
          new Producer(t).start();
  new Consumer(t).start();
    }
}  
class Tickets  //票类 
{
int number=0;        //票类号
int size;             //总票数 
boolean available=false;   //目前是否有票可售
public Tickets(int size)
{
this.size=size;
}
}class Producer extends Thread //存票线程
{
Tickets t=null;
public Producer(Tickets  t)
{
this.t=t;
}
public void run()
{
while (t.number<t.size)   //循环条件为存票序号小于总票数
{
synchronized(t)
{
     System.out.println("Producer puts ticket "+(++t.number));
         t.available=true;  //可以卖票
}
}
}
}class Consumer extends Thread   //售票纯种 
{
Tickets t=null;
int i=0;
public Consumer(Tickets t)
{
this.t=t;
}
public void run()
{
while (i<t.size)   //循环条件为售票序号小于总票数
{
synchronized(t)
{
if (t.available=true&&i<=t.number)  //有票可售且小于总票数
        {
       System.out.println("Consumer buys ticket "+(++i));
        }            /* if(i==t.number)
    {
                        t.available=false;
}*/

           if(i==t.number)   //如果票已售到当前序号,则不可售
    {
   try
   {
Thread.sleep(1);
   }
   catch (Exception e)
   {
   }
                        t.available=false;
}
    } } }
}
//java语言程序设计   郑莉  P236我现在想问的时为什么不用这个             /* if(i==t.number)
    {
                        t.available=false;
}*/ 而用            if(i==t.number)   //如果票已售到当前序号,则不可售
    {
   try
   {
Thread.sleep(1);
   }
   catch (Exception e)
   {
   }
                        t.available=false;
} 执行一结果不一样、 后一个执行的准确 前一个 有这样的情况 有 先卖了第9张
才开始存第9张 为什么呢 不是用了 
synchronized(t)吗 想不通上传不上图片?
其中有 buys ticket 9
puts ticket 9就是不可  SLEEP里情况下 
 

解决方案 »

  1.   

    因为在线程中是同时运行的,所以要考虑到在每个计算机的每次运行中的结果都是有可能不一样的.那并不是错误,看怎么去理解;
    虽然你在 Producer(t)和Consumer(t)的方法中都用了synchronized(t),可是不可避免的是他们是可以同时运行的,如果在运行
    if   (t.available=true&&i <=t.number)     //有票可售且小于总票数 
                    { 
                  System.out.println("Consumer   buys   ticket   "+(++i)); 
                    } 
                   if(i==t.number) 
            { 
                    t.available=false; 
    }
    中的t.available=false;之后马上运行了
    synchronized(t) 

              System.out.println("Producer   puts   ticket   "+(++t.number)); 
                      t.available=true;     //可以卖票 

    中的t.available=true; 
    这样再运行
    if   (t.available=true&&i <=t.number)     //有票可售且小于总票数 
                    { 
                  System.out.println("Consumer   buys   ticket   "+(++i)); 
                    } 
                   if(i==t.number) 
            { 
                    t.available=false; 
    }
    这时if   (t.available=true&&i <=t.number)  中 i=t.number 所以运行
    System.out.println("Consumer   buys   ticket   "+(++i)); 时就出现了
    先卖了第9张 
    才开始存第9张 
    因为打印的是i+1的值.
    而用
    Thread.sleep(1); 这样就让Producer 有时间运行,避免了这种情况的发生
    或者你把这时if   (t.available=true&&i <=t.number)  中 i<=t.number 改为i<t.number试试
      

  2.   

    以你这样的理解是这样的    Producer(t)和Consumer(t)的方法中都用了synchronized(t),可是不可避免的是他们是可以同时运行的、这是什么意思 呢 ?书:就是  synchronized(t)把他后面的代码执行完才把 锁放掉吗  你现在说的是在synchronized(t)
    -----代码内出现的切换 不是吗------  书上说的是  synchronized(t)把他后面的代码执行完才把 锁放掉可能书的说的错了。
      

  3.   

    如果你有这本书的话  你可以看一下  就是 书上为了解决这种线程代码执行时  切换到其他线程代码时  才引出了  synchronized(t) ----->不让 代码内出现的切换
      

  4.   

    synchronized(t)的意思是在synchronized(t){}中的语句只有一个线程可以访问
    可以是你写在了两个方法中,用了两个synchronized(t),
    意思是说在执行一个方法的时候只有一个线程可以运行synchronized(t),别的必须等待,
    而另一个方法也是如此,我想说的就是这个意思
    等晚上看看说再说吧
      

  5.   

    好的  我知道了  你说的是  在他的时间片内 我 忘记想这个了 是这样吗  你看  楼上的 

    synchronized(t)
    {
     ......
    A:
    ........
    }
    当他的时间片在A处用完了  就 放掉锁  
    下次得到锁 了 就直接在A处继续执行下载就是样吗