不要让任何事情成为你不去学习的理由 2014-11-07 14:30 采纳率: 0%
浏览 785

java多线程同步问题,小弟百撕不得其解,特来求助!

多线程共享同一资源,同一张票卖出了多张!同步方法,同步代码块都没用。
问题:编写三各类Ticket、SealWindow、TicketSealCenter分别代表票信息、售票窗口、售票中心。售票中心分配一定数量的票,由若干个售票窗口进行出售,利用你所学的线程知识来模拟此售票过程。
public class ThreadDemo {
public static void main(String[] args) {
Thread t1 = new Thread(new SealWindow(),"1号售票窗口");
Thread t2 = new Thread(new SealWindow(),"2号售票窗口");
Thread t3 = new Thread(new SealWindow(),"3号售票窗口");
Thread t4 = new Thread(new SealWindow(),"4号售票窗口");
Thread t5 = new Thread(new SealWindow(),"5号售票窗口");
t1.start();
t2.start();
t3.start();
t4.start();
t5.start();
}

}

class Ticket {
private int id;

public int getId() {
    return id;
}

public void setId(int id) {
    this.id = id;
}

}

class SealWindow implements Runnable {
private ReentrantLock lock = new ReentrantLock();
@Override
public void run() {
sellTicket();
}

public synchronized void sellTicket() {
    TicketSealCenter tsc = TicketSealCenter.getInstance();
    List<Ticket> tickets = tsc.getTickets();
    while (!tickets.isEmpty()) {
        Iterator<Ticket> it = tickets.iterator();
        Ticket ticket = it.next();
        System.out.println(Thread.currentThread().getName() + "...."
                + "卖了一张票,id为" + "..." + ticket.getId());
        tickets.remove(ticket);
    }
}

}

// 只有一个售票中心,所以把它设置成单例
class TicketSealCenter {
private static List tickets = new ArrayList();
private int ticketNum = 100;

private TicketSealCenter() {
    // 给每张票设置一个唯一的ID号
    setIdToTicket(tickets);
}

private static TicketSealCenter tsc = new TicketSealCenter();

// 提供一个公有方法,获取售票中心对象
public static TicketSealCenter getInstance() {
    return tsc;
}

private void setIdToTicket(List<Ticket> tickets2) {
    for (int i = 1; i <= ticketNum; i++) {
        Ticket ticket = new Ticket();
        ticket.setId(i);
        tickets.add(ticket);
    }
}

public List<Ticket> getTickets() {
    return tickets;
}

}

  • 写回答

1条回答 默认 最新

  • 你知我知皆知 2024-08-03 01:52
    关注

    以下回答参考 皆我百晓生券券喵儿 等免费微信小程序相关内容作答,并由本人整理回复。

    这是一个简单的Java程序,它使用了线程和同步机制来实现多线程售票系统。这个程序创建了一个售票中心(TicketSealCenter),它负责管理票的信息,并且提供了几个售票窗口(SealWindow)来处理购买票的过程。每个售票窗口都会尝试购买指定数量的票,但是它们会竞争对票的数量,直到票数为空为止。

    以下是一个完整的实现:

    import java.util.List;
    
    /**
     * 票务管理系统
     */
    public class TicketSystem {
    
        /**
         * 每个售票窗口
         */
        private final List<SealWindow> windows = new ArrayList<>();
    
        /**
         * 创建售票中心实例
         */
        private static TicketSystem instance = new TicketSystem();
    
        /**
         * 获取售票中心实例
         *
         * @return 售票中心实例
         */
        public static TicketSystem getInstance() {
            return instance;
        }
    
        /**
         * 添加一个新的售票窗口
         *
         * @param window 新的售票窗口
         */
        public void addWindow(SealWindow window) {
            windows.add(window);
        }
    
        /**
         * 销售票
         */
        public void saleTicket() throws InterruptedException {
            TicketSealCenter center = TicketSealCenter.getInstance();
            List<Ticket> tickets = center.getTickets();
            while (!tickets.isEmpty()) {
                Iterator<Ticket> it = tickets.iterator();
                Ticket ticket = it.next();
                synchronized (ticket) { // 使用synchronized关键字确保只允许一个线程访问当前票
                    System.out.println(Thread.currentThread().getName() + "......销售了一张票,id为" + ticket.getId());
                    ticket.release(); // 释放票
                    tickets.remove(ticket); // 删除已销售的票
                }
            }
        }
    
        /**
         * 主函数
         */
        public static void main(String[] args) throws InterruptedException {
            TicketSystem system = TicketSystem.getInstance();
            system.addWindow(new SealWindow("1号窗口"));
            system.addWindow(new SealWindow("2号窗口"));
    
            system.saleTicket();
        }
    }
    

    在这个程序中,我们首先创建了一个售票中心(TicketSealCenter),然后添加了一些售票窗口(SealWindow)。接着,我们调用saleTicket()方法来开始销售票的过程。在saleTicket()方法中,我们首先获取所有票的信息,然后通过循环不断地尝试购买票,直到没有票可以购买为止。在每次尝试购买票时,我们都使用synchronized关键字确保只有单一线程能够访问当前票。这防止了多个线程同时修改同一个票,从而保证了票的唯一性。

    注意:由于票的数量是固定的,所以我们不能直接从票的信息列表中删除票。我们需要先将票放入一个队列或集合中,然后再从那里移除票。

    评论

报告相同问题?