解决方案 »

  1.   

    很简单 sellticket和getticketnum两段代码之间发生了数值的修改 你应该将这两这方法 放在一个锁里面
      

  2.   

    使用java的关键,把变量锁住,或者使用线程安全的数组,如Vector等或者添加关键字 volatile, synchronized 等
      

  3.   

    在卖票和显示信息的过程中加上同步:
    while (ticket.getTicketNum() > 0) 
    {
    synchronized(ticket)
    {
    ticket.sellTicket();
    System.out.println(Thread.currentThread().getName()
    + "卖了一张票,剩余" + ticket.getTicketNum() + "张票");
    }
    }
      

  4.   

    卖票过程没有错误,只是打印出来的信息欺骗了你,也就是说打印的不是卖的。
    你这样改下:
    先改下卖票方法
    public synchronized int sellTicket() {
            ticketNum --;
            return ticketNum;
        }
    然后改下run方法
    while(ticket.getTicketNum()>0){
            System.out.println(Thread.currentThread().getName() + "卖了一张票剩余"+ticket.sellTicket()+"张票" );
            }
    这样应该就可以了。
    个人感觉查询票数的方法getTicketNum没必要定义为同步方法,因为在这个方法里没有修改ticketNum。
      

  5.   

    你的run()方法也得是原子性的
      

  6.   

    楼主卖票本身没问题。只是打印顺序有问题,你的锁只有在sellTicket()方法内才有效。你想想,当一个线程执行完该方法,你的锁已经打开,这时候其他线程也可以卖票了。但是你的打印语句是在卖票方法之后再执行。。所以当然可能会出现打印的结果不是你期望的。解决方法:将锁的位置加在线程实现代码里。打印语句直接放在卖票方法sellTicket()里。public class SellTiketDemo {    public static void main(String[] args) {

            Ticket ticket = new Ticket();
            BuyTicket buyTicket = new BuyTicket();
            buyTicket.setTicket(ticket);
            Thread Thread1 = new Thread(buyTicket,"窗口1");
            Thread Thread2 = new Thread(buyTicket,"窗口2");
            Thread Thread3 = new Thread(buyTicket,"窗口3");
            Thread1.start();
            Thread2.start();
            Thread3.start();
            }} class Ticket {
        private int ticketNum = 1000;
       
        public  void sellTicket() {
    ticketNum--;
    System.out.println(Thread.currentThread().getName() + "卖了一张票剩余"+this.getTicketNum()+"张票" );
            
        }
        public int  getTicketNum() {
            return ticketNum;
        }
         
    }
     
     class BuyTicket implements Runnable {
         private Ticket ticket;
          
         public  void setTicket(Ticket ticket) {
             this.ticket = ticket;
         }
      
         @Override
         public synchronized void run() {
             while(ticket.getTicketNum()>0){
                
                 ticket.sellTicket();
      
             }
         }
      
     }
      

  7.   

    刚才运行了下,虽然共享数据不会出错了,貌似多线程的效率没体现出来,。改了一下
    public class SellTiketDemo {    public static void main(String[] args) {

            Ticket ticket = new Ticket();
            BuyTicket buyTicket = new BuyTicket();
            buyTicket.setTicket(ticket);
            new Thread(buyTicket,"窗口1").start();;
            new Thread(buyTicket,"窗口2").start();;
            new Thread(buyTicket,"窗口3").start();;
        }} class Ticket {
        private int ticketNum = 1000;
       Object lockObject=new Object();
     
       
           public  void sellTicket() {
       synchronized (lockObject) {
        ticketNum--;
        System.out.println(Thread.currentThread().getName() + "卖了一张票剩余"+this.getTicketNum()+"张票" );
    }

            
        }
       
       
        public  int  getTicketNum() {
    synchronized (lockObject) {
          return ticketNum;
    }
          
            
        }
         
    }
     
     class BuyTicket implements Runnable {
         private Ticket ticket;
          
         public  void setTicket(Ticket ticket) {
             this.ticket = ticket;
         }
      
         @Override
         public  void run() {
     
                while(ticket.getTicketNum()>0){
            
                 ticket.sellTicket();
      
                } 
             }
         
      
     }
      

  8.   

    。。楼主不好意思。。刚才的代码还是会有点问题,同步代码块没把获取票数加进去,导致有线程先获取票数判断通过,再去买票。。导致票数结果又-1,-2.这次的代码是终极版本。。调了半小时。。没问题了。。请参考。public class SellTiketDemo {    public static void main(String[] args) {

            Ticket ticket = new Ticket();
            BuyTicket buyTicket = new BuyTicket();
            buyTicket.setTicket(ticket);
            new Thread(buyTicket,"窗口1").start();;
            new Thread(buyTicket,"窗口2").start();;
            new Thread(buyTicket,"窗口3").start();;
        }} class Ticket {
        private int  ticketNum = 1000;       public  void sellTicket() {
        ticketNum--;
       
        }
       
       
        public   int  getTicketNum() {
         return ticketNum;
        }
    }
     
     class BuyTicket implements Runnable {
         private Ticket ticket;
          
         public  void setTicket(Ticket ticket) {
             this.ticket = ticket;
         }
      
         @Override
         public  void run() {
      while(true){ //线程开始执行之后,先进入循环,再执行同步代码。这样避免了数据读写不同步的现象。
     synchronized (ticket) {
       
      if(ticket.getTicketNum()>0){
              ticket.sellTicket();
              System.out.println(Thread.currentThread().getName() + "卖了一张票剩余"+ticket.getTicketNum()+"张票" );
            }
       else {
            break;
       }
    }
     } 
          }    
     }
    运行结果:
      

  9.   

    这样肯定会有问题.
    虽然买票过程同步了,但是获取票数信息的时候却和之前买票过程不同步,这个过程中会有其它线程改变票数,这个时候你得到的不是及时的你买完票之后的票数.
    public synchronized void sellTicket() {
            ticketNum --;
    System.out.println(Thread.currentThread().getName() + "卖了一张票剩余"+ticketNum+"张票" );//直接在买票方法里及时显示票数信息即可.
        }