/*
项目:用多线程设计一个模拟火车站售票大厅的工作情形。
问题描述:火车站有许多售票窗口,有些开放,有些不开放。顾客进入火车站售票厅后,到某个售票窗口排队等候,排到了就办理业务,然后离去。如图2.1所示。
*/
/*
*共有五个类:
*SimulateRailwayStation:具体运行主类;
*RailwayStation:火车站售票大厅类
*Agent类:代表火车站售票窗口类;
*Customer类:顾客类;
*List类:存储类
*/
import java.util.Date;
import java.awt.*;
import java.awt.event.*;
public class SimulateRailwayStation extends Frame implements ActionListener
{
//预设火车站售票大厅有10个售票窗口
protected static final int NUM_AGANTS=10;
//预设目前正在售票的窗口为6个
protected static final int NUM_INITIAL_AGANTS=6;
//设置每个窗口办理售票业务的时间
protected static final int BUSINESS_DELAY=6000;
//设置有10辆火车的座位可以出售
protected static final int MAX_TRAIN_NUM=10;
//设置每个窗口从一个顾客完成到下一个顾客开始的时间间隔
protected static final int MAX_NO_CUSTOMERS=200;
//定义按钮,手动添加顾客。
private Button addcus=new Button("添加顾客");
//定义按钮,模拟顾客自己离开
private Button delcus=new Button("顾客离去");
//定义按钮,增加售票窗口
private Button addagent=new Button("增加售票窗口");
//定义按钮,关闭售票窗口
private Button delagent=new Button("关闭售票窗口");
//10辆火车班次的信息
protected static String[] train_num={"南京->北京,46次","南京->上海,34次","南京->福州,231次","南京->杭州,65次","南京->武汉,112次","南京->成都,77次","南京->天津,21次","南京->徐州,134次","南京->乌鲁目齐,335次","南京->合肥,456次"};
//与上面的信息对应的每辆火车的票务信息
protected static int[] tickets={50,70,50,50,50,120,60,100,50,50};
//实例化火车站售票大厅类
private RailwayStation railwaystation=new RailwayStation();
//建立窗体适配器,能关闭窗口
private class WindowCloser extends WindowAdapter
{
public void windowClosing(WindowEvent we)
{
railwaystation.stop();
System.exit(0);
}
}
//构造方法,完成界面初始化
public SimulateRailwayStation()
{
super("Simulation RailwayStation");
//设置面板
Panel buttons=new Panel();
buttons.setLayout(new FlowLayout());
//在面板中添加按钮
buttons.add(addcus);
buttons.add(delcus);
buttons.add(addagent);
buttons.add(delagent);
//对按钮设置监听
addcus.addActionListener(this);
delcus.addActionListener(this);
addagent.addActionListener(this);
delagent.addActionListener(this);
//对窗体适配器设置监听
addWindowListener(new WindowCloser());
setLayout(new BorderLayout());
add("North",railwaystation);
add("South",buttons);
setSize(500,200);
validate();
pack();
show();
//调用火车站售票大厅类的start()方法,开始售票工作
railwaystation.start();
}
public void actionPerformed(ActionEvent ae)
{
if(ae.getSource()==addcus)
{
//新增顾客
railwaystation.generateCustomer();
}
else if(ae.getSource()==delcus)
{
}
else if(ae.getSource()==addagent)
{
//增加售票窗口
railwaystation.addAgent();
}
else if(ae.getSource()==delagent)
{
//关闭服务窗口
railwaystation.retireAgent();
}
}
public static void main(String[] args)
{
SimulateRailwayStation smlt=new SimulateRailwayStation();
}
}
/* 火车站售票大厅类 */
class RailwayStation extends Panel implements Runnable
{
//定义售票窗口数组Agent[]
protected Agent[] agent=new Agent[SimulateRailwayStation.NUM_AGANTS];
protected Label[] labelAgent=new Label[SimulateRailwayStation.NUM_AGANTS];
protected Label labelQueue=new Label("正在等待的顾客数:0");
protected Label labelServed=new Label("已经服务的顾客数:0");
//定义可以进行售票服务的窗口
protected int numAgents=SimulateRailwayStation.NUM_INITIAL_AGANTS;
//定义存放已服务过的顾客数
public static int numCustomerServered=0;
private Thread thread=null;
public RailwayStation()
{
setup("各窗口实时状态显示:");
}
//显示各售票窗口的实时工作状态
private void setup(String title)
{
//定义售票窗口的工作状态面板
Panel agentPanel=new Panel();
agentPanel.setLayout(new GridLayout(SimulateRailwayStation.NUM_AGANTS,1));
//各售票窗口的工作状态
for(int i=0;i<SimulateRailwayStation.NUM_AGANTS;i++)
{
if(i<numAgents)
{
labelAgent[i]=new Label("窗口"+(i+1)+":空闲中...");
agentPanel.add(labelAgent[i]);
//实例化售票窗口
agent[i]=new Agent(i);
//售票窗口开始售票服务
agent[i].start();
}
else
{
labelAgent[i]=new Label("窗口"+(i+1)+":暂停服务!");
agentPanel.add(labelAgent[i]);
}
}
//定义顾客候票情况面板
Panel otherPanel=new Panel();
otherPanel.setLayout(new GridLayout(2,1));
otherPanel.add(labelQueue);
otherPanel.add(labelServed);
setLayout(new BorderLayout());
//显示各售票窗口的工作状态安排在下部
add("South",agentPanel);
//显示顾客候票状况安排在中部
add("Center",otherPanel);
//显示调用本方法 setup()的参数安排在上部
add("North",new Label(title));
}
//开始工作
public void start()
{
if(thread==null)
{
thread =new Thread(this);
//启动线程
thread.start();
}
}
//线程,调用显示实时售票状况的updateDisplay()方法
public void run()
{
while (true)
{
this.updateDisplay();
}
}
//实时处理售票的状况
public void updateDisplay()
{
//定义在本窗口等候的顾客数
int totalSize=0;
//对可以服务的窗口进行循环
for(int i=0;i<numAgents;i++)
{
//getCIdOfHandling()方法为正在办理业务的顾客编号
if(agent[i].getCIdOfHandling()!=0)
{
//统计在本窗口等候的顾客数
totalSize+=agent[i].getCusCountOfQueue();
String s="窗口"+(i+1)+":正在办理顾客"+agent[i].getCIdOfHandling()+"业务";
//显示在本窗口等候的顾客数
if(agent[i].getCusCountOfQueue()>0)
labelAgent[i].setText(s+"["+agent[i].getCusOfQueue()+"正在等待]");
else
labelAgent[i].setText(s);
}
else
{
labelAgent[i].setText("窗口"+(i+1)+":空闲中...");
}
}
for(int i=numAgents;i<SimulateRailwayStation.NUM_AGANTS;i++)
labelAgent[i].setText("窗口"+(i+1)+":暂停服务!");
labelQueue.setText("正在等待的顾客数:"+totalSize);
labelServed.setText("已经服务的顾客数:"+numCustomerServered);
}
//火车站售票窗口关闭
public void stop()
{
thread=null;
for(int i=0;i<numAgents;i++)
{
//停止售票服务
agent[i].halt();
}
}
//添加窗口
public void addAgent()
{
if(numAgents<SimulateRailwayStation.NUM_AGANTS)
{
agent[numAgents]=new Agent(numAgents);
agent[numAgents].start();
numAgents++;
}
}
//关闭窗口,该方法暂时没有使用
public void retireAgent()
{
if(numAgents>1)
{
agent[numAgents-1].halt();
numAgents--;
}
}
//接待顾客的方法
public void generateCustomer()
{
//所有工作窗口的队列中,至少有一个顾客在排队时为真.
boolean allAgentQueueHasOne=true;
/* 如果所有正在工作窗口的队列中至少有一个顾客在排队,
就把新顾客添加到队列最少的那个队.
否则,就把顾客添加到没有业务处理的窗口中.
*/
//对可以服务的窗口进行循环
for(int i=0;i<numAgents;i++)
{
//如果本窗口队列中没有顾客
if(agent[i].getCusCountOfQueue()==0 && agent[i].getCIdOfHandling()==0)
{
//添加新顾客
agent[i].joinNewCustomer(new Customer());
allAgentQueueHasOne=false;
break;
}
}
//如果所有工作窗口都有顾客在等候
if(allAgentQueueHasOne)
{
//定义变量index存放最少等候顾客数的窗口编号
int index=0;
//对可以服务的窗口进行循环
for(int i=0;i<numAgents;i++)
{
if(agent[i].getCusCountOfQueue()<agent[index].getCusCountOfQueue())
{
index=i;