因为你的synchronized是加在对象上的,但是你在建线程的时候,又新建了好几个匿名对象,这就意味着每个对象都有它自己的synchronized,所以这几个线程也就不互斥,因为它们不共享synchronized。正确的做法是只需要建一个对象,然后让这几个线程共享一个对象。像“1号窗口”、“2号窗口”可以设置为线程的名字,而不是对象的属性。

解决方案 »

  1.   


    public class TicketDemo {
     
        public static void main(String[] args) { 
         SealWindow myWindow=new SealWindow();
            new Thread(myWindow,"1号窗口").start();
            new Thread(myWindow,"2号窗口").start();
            new Thread(myWindow,"3号窗口").start();
            new Thread(myWindow,"4号窗口").start();
        }
    }
    //票信息
    class Ticket {
        private static int ticketid;
     
        public static int getTicketid() {
            return ticketid;
        }
         
        public static void setTicketid(int ticket) {
            ticketid = ticket;
        }
    }
    //售票窗口
    class SealWindow implements Runnable {
        TicketSealCenter tsc = null;
        public SealWindow(){
            tsc = TicketSealCenter.getInstance();
        }
        public void sellTicket(){
            while(!tsc.hasTicket()){
               // System.out.println(Thread.currentThread().getName()+"卖出了第" + tsc.getid()+"号票!");
                if (tsc.hasTicket()) {
                    System.out.println(Thread.currentThread().getName()+"的票已卖完!!");
                }
            }
             
        }
        public void run() {
            sellTicket();
        }
    }
    //售票中心
    class TicketSealCenter {
        private static TicketSealCenter tsc = new TicketSealCenter();
        private static Ticket ticket = new Ticket();
         
        private static int sumticket = 100;
        private static boolean flag = false;
         
        private TicketSealCenter(){}
         
        public static TicketSealCenter getInstance(){
            return tsc;
        }
        //询问是否有票,设置票面ID,并返回该ID
        public static synchronized boolean hasTicket(){
            if(sumticket > 0){
                ticket.setTicketid(sumticket);
                System.out.println(Thread.currentThread().getName()+"卖出了第" + tsc.getid()+"号票!");
                sumticket--;
            }else {
                flag =true;
            }
            return flag;
        }
        public int getid(){
            return ticket.getTicketid();
        }
    }
      

  2.   


    您说的不对吧,不是因为创建了多个对象,而是因为
     while(!tsc.hasTicket()){
                System.out.println(ticketname+"卖出了第" + tsc.getid()+"号票!");
    这句并不能保证调用完成tsc.hasTicket方法之后马上执行输出语句,所以要不给这句上面加锁,但是只能加静态锁。或者就是把这句输出语句加到tsc.hasTicket他的实现里面。
      

  3.   

    恩  主要楼主用的是单例设计模式,不管创建多少个SealWindow,共享的都是一个TicketSealCenter对象。你的意思我在上述代码中已经有所体现了。
      

  4.   

    很简单的代码,撸主给弄好凌乱,很简单的锁机制,撸主却乱加。
    减票方法你是加锁了,可是获取票的方法你考虑过么?
    如果一个线程都执行了public static synchronized boolean hasTicket()这个方法后,执行权交给另一个线程,另一个线程也跑了这个方法,后面类推,接着多个线程开始执行public int getid()方法,你觉得票是多了呢,还是少了呢?
      

  5.   

    多谢了 我刚开始学java 思路有些混乱 之后自己又缕清了思路 重新写了下 现在不会出现安全问题了 还是十分的感谢你