昨天面试一公司,应面试官要求,用synchronized、notify、wait实现一个火车票卖票程序,要求生成者不断的往队列中插入唯一的票通知消费者取票,消费者取走这唯一的票再通知生产者放票,如此循环。
参照疯狂Java讲义中存钱的例子实现,代码如下:
Ticket.java
import java.util.ArrayDeque;
public class Ticket {
ArrayDeque ticket = new ArrayDeque();
long ticketNum = 1;
public synchronized void sell()//售票函数
{
try
{
System.out.println("当前票数量:" + ticket.size());
if(ticket.size() > 0) //取票
{
System.out.println(Thread.currentThread().getName() +
" 取走第:" + ticket.pop() + "张票.");
notify();
}
else
{
System.out.println(Thread.currentThread().getName() +
"等待售票员放票.");
// Thread.sleep(1000);
wait();//等待放票
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public synchronized void put()
{
try
{
System.out.println("当前票数量:" + ticket.size());
if(ticket.size() > 0)
{
System.out.println(Thread.currentThread().getName() +
"等待乘客取票.");
//Thread.sleep(1000);
wait();//等待取票
}
else//放票
{
ticket.push(ticketNum);
System.out.println(Thread.currentThread().getName() +
"放入第:" + ticketNum + "张票.");
ticketNum ++;
notify();
}
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
PutTicketThread.java
public class PutTicketThread extends Thread{
private Ticket ticket;
public PutTicketThread(String name, Ticket ticket)
{
super(name);
this.ticket = ticket;
}
public void run(){
while(true)//循环放票
{
ticket.put();
}
}
}
SellTicketThread.java
public class SellTicketThread extends Thread {
private Ticket ticket;
public SellTicketThread(String name, Ticket ticket) {
super(name);
this.ticket = ticket;
}
public void run() {
while (true) {//循环取票
ticket.sell();
}
}
}
TestMain.java
public class TestMain {
public static void main(String[] args) throws InterruptedException
{
Ticket ticket = new Ticket();
new PutTicketThread("售票员 1", ticket).start();
//new PutTicketThread("售票员 2", ticket).start();
new SellTicketThread("张三", ticket).start();
//new SellTicketThread("李四", ticket).start();
//new SellTicketThread("王五", ticket).start();
}
}另外如果有多个售票员或者买票员,需要将Ticket.java中的notify改为notifyAll.否则可能导致程序运行达不到预期的效果,例如有两个售票员和一个买票员,假如其中的一个售票员和买票员都在wait,这个时候另外一个售票员放完票后调用notify唤醒的是在等待的售票员,这个时候由于有票,所以它也会wait,而买票员的画没有notify将其唤醒了。
本文介绍了如何使用Java中的synchronized、notify和wait关键字实现一个火车票卖票程序,通过创建Ticket类来模拟售票和取票的过程,并通过PutTicketThread和SellTicketThread线程类来实现生产者和消费者的功能。为了确保线程间的正确同步,当票售罄时会使用wait方法挂起线程,直到有新票可用时通过notify或notifyAll方法唤醒等待的线程。
2907

被折叠的 条评论
为什么被折叠?



