1.1 案例介绍
本案例将演示在十字路口车辆运行的简单状况,用Java多线程技术和IBM提供的并发组件Amino实现在有交通信号灯控制情况下多车辆的运行的简单控制。
1.1.1 目的和意义
模拟交通信号控制下路口的交通情况,也是非常有实际意义的。在现实生活中,一个路口的交通信号灯可能要化很长的时间来调试。如果将这个过程用程序来模拟,那将可以节省时间,同时也可以考虑更多的复杂情况。
但是模拟交通信号控制下路口的交通情况,本身是一件较复杂的事情,因为要涉及到众多的线程,线程间涉及数据共享和同步。程序的调试也比较困难。
Java语言提供了良好的线程技术,同时Amino组件提供了并发安全的数据结构。本案例可以验证Amino组件在多线程情况下数据的正确性已以及程序的稳定性。
1.1.2 主要界面
本案例将演示在十字路口车辆运行的简单状况:先以1张背景图作为街道及十字路口的的模拟地形图。在本图上将显示双向两车道的带人行横道的十字街道。启动线程控制南北及东西四个方向的交通信号灯和信号的持续时间。在信号灯的指挥下,实现车辆的有限控制,如红灯停,绿灯行(黄灯按绿处理)等功能。程序的主要界面如图1。
1.1.3 主要功能
在本图上将显示双向两车道的带人行横道的十字街道。启动两个线程控制南北及东西四个方向的交通信号灯和信号的持续时间。
在有交通信号灯控制的场景中,启动一个线程再在各个路口随机添加车辆,每个车辆本身就是一个线程,它的运行要受到交通信号灯的简单控制,即红灯停,绿灯和黄灯通过。在十字路口中心的路口交汇区,车辆有可能撞车,本案例按照黄灯通过的方式作简单处理。
一辆车走完过了街道,即该车的线程结束了,该车也就在屏幕中消失了。
对于十字路口的街道,设置了一个车辆的运行总数。当场中的车辆没有达到运行总数,产生车辆的线程将继续向场中添加车辆。当场中的车辆达到运行总数,产生车辆的线程的将停止添加车辆。当有车辆消失后,场中的车辆少于运行总数,这时,产生车辆的线程的将继续添加车辆。也就是说,场中的车辆总数是一个动态的数目。同时,可以看到车辆运行是川流不息的。
另外,在程序的菜单中,设置了整个系统的暂停和恢复。
1.1.4 主要操作流程.
启动程序后程序自动进入运行状态,默认总车辆数为20,但也可以进行一下的一些调整:
1) 流量控制,例如输入60,则系统将为信号灯的转换时间为15秒。
2)整个系统的暂停和恢复
1.2 安装运行.
本系统的运行需要Amnio组件和JavaSE6 的支持。
将附件的Eclispe工程导入Eclispe即可运行。
由于系统采用了Amino组件,需要下载Amino组件的amino-cbbs-0.3.1.jar文档,并添加到系统的库文件路径中去。
1.3 程序分析
分析程序的执行流程和主要功能的实现,并对主要的类进行说明。
在本程序中涉及到的类如下:
Trafficlight:主线程,启动其他线程;
Roadpanel:该类继承Jpanel,是需要显示的组件的容器,如信号灯、时间、车辆集合。
ImageFrame:主窗口,在上面添加roadpanel的实例,设置菜单等。
Controlew:控制东西方向信号灯的线程
Controlns:控制南北方向信号灯的线程
Car: 车辆线程
EnterRoad:随机向路口添加车辆的线程
Freshpanel:刷新显示Roadpanel的线程
ContralCarList:当线程正常结束,将Car的实例移出车辆集合。
Four:存放类变量的类,用来存放东西、南北方向信号灯对车辆速度影响的权重,其值为1或0,是一种全局公共变量的设置方式。
1.3.1 程序执行流程
1.3.2 多线程并发分析
在程序执行的过程中,会产生多个线程:
1) 东西信号灯控制线程,主要控制东、西两个方向的信号及信号持续时间,
2) 南北信号灯控制线程,主要控制南、北两个方向的信号及信号持续时间,
3) 添加车辆添加的线程,该线程每间隔一个随机时间后就会向场中添加一辆车子(每一辆车辆就是一个线程),
该线程可能有很多。在默认情况下,场类将产生20辆车(20个线程)。
4) 车辆线程,车辆本身是一个运动的,需要一个线程模拟其运动规律。
5) 刷新线程,为了保证其显示效果,把车辆的重新绘制统一安排在一个线程中。
6) 车辆总数控制线程:该线程为独立线程,用来监控车线程是否是活的。当车的线程正常结束,将它的实例移出车辆集合。
在Roadpanel的实例中,我们设置了基于Amino组件的LockFreeList实体carlist,如下:
LockFreeList<Car> carlist=new LockFreeList<Car>();
LockFreeList实际上是一个线程安全的Amino并发组件,用来存放整个街道所有车辆。在不同的线程中,可以安全地对去做移出、添加等操作。
1.3.3 类说明
本程序主要包含的类分为一个包:sample.traff9包里面包含了程序的所有类:
表1-1 类说明
包 |
类名字 |
说明 |
Sample.traff9 |
Trafficlight |
主线程,定义一些实例,启动其他线程; |
Roadpanel |
该类继承Jpanel,是需要显示的组件的容器,如信号灯、时间、车辆集合。 |
|
ImageFrame |
主窗口,在上面添加roadpanel的实例,设置菜单等 |
|
Controlew |
控制东西方向信号灯的线程 |
|
Controlns |
控制南北方向信号灯的线程 |
|
Car: |
车辆线程。 |
|
EnterRoad |
随机向路口添加车辆的线程。 |
|
Freshpanel |
刷新显示Roadpanel的线程。 |
|
ContralCarList |
当线程正常结束,将Car的实例移出车辆集合。 |
|
Four |
存放类变量的类,用来存放东西、南北方向信号灯对车辆速度影响的权重,其值为1或0,是一种全局公共变量的设置方式。 |
1.3.4 主要功能实现分析
下面对本程序中的主要功能作一定的分析。本程序中,主要有四个难点:东西信号灯、南北信号灯的转换及显示、车辆的随机添加和移出、车辆对红绿灯信号的响应以及整体动画显示的质量控制。
1) 东西信号灯、南北信号灯的转换及显示
东西信号灯控制类为Controlew,主要的代码如下:
class Controlew implements Runnable{
private int i=0,p,n,e,tp=0;
private String s="",w="",t="";
private Roadpanel rpanel;
Date date;
boolean v=true;
public Controlew(Roadpanel rp){
rpanel=rp;
}
public void run()
{
out:while(true)
{
synchronized(this)
{
if(!v) {
try{
this.wait();
}catch(Exception e)
{e.printStackTrace();}
}
rpanel.n1.setForeground(Color.green); Four.n1=0;
rpanel.n2.setForeground(Color.red); Four.e1=1;
rpanel.n3.setForeground(Color.red); Four.w1=1;
rpanel.n.setForeground(Color.red); Four.s1=0;
rpanel.e1.setForeground(Color.green);
rpanel.e2.setForeground(Color.green);
rpanel.e3.setForeground(Color.green);
rpanel.e.setForeground(Color.green);
rpanel.s1.setForeground(Color.red);
rpanel.s2.setForeground(Color.red);
rpanel.s3.setForeground(Color.green);
rpanel.s.setForeground(Color.red);
rpanel.w1.setForeground(Color.green);
rpanel.w2.setForeground(Color.green);
rpanel