本文实例为大家分享了java多线程模拟交通灯管理系统的具体代码,供大家参考,具体内容如下
一、项目业务逻辑分析
项目需求:模拟实现十字路口的交通灯管理系统逻辑,要求如下:
- 异步随机生成按照各个路线行驶的车辆,例如由北向南行驶的车辆、由东向南行驶的车辆。
- 信号灯忽略黄灯,只考虑红灯和绿灯的情况。
- 左转受信号灯控制,右转车辆不受信号灯控制,其他情况与现实生活的逻辑相同。
- 注:南北向车辆和东西向方向车辆交替放行,同方向等待车辆应先放行直行车辆,而后再放行左转车辆。
- 每辆车通过路口所需时间为1秒(提示:可以通过线程的sleep方法模拟)。
- 随机生成车辆,时间间隔以及红绿灯交换时间自定。
- 不要求GUI,只考虑系统逻辑实现。可在在终端log方式模拟。
首先了解一下现实中十字路口的交通灯的业务逻辑(为此我大晚上在十字路口仔细观察了半个小时,缺少生活啊。),直接上图吧,直观明了:
额,乍一看有点乱,仔细一想很简单,就是东西南北四条路每条路都有三个去向,左转、右转和直行,这样一个十字路口就有了12个行驶方向。每个方向都有一个指示灯,也就是12个信号灯,如果每个信号灯都单独控制,那就麻烦多了,而且很不科学,得一天24小时堵车。需求第3点说明右转不受信号灯控制,其实现实生活照也是这样,一般右转车辆不受控制的(比较繁忙的路口受控制),随时可以转,也就是说永远是绿色等,想不通为什么这样设计?而 对立面的灯是同步变化的,同时绿或者同时红,这样只需要系统控制一个方向的灯就可以了。最后我们只需要控制四个方向的灯就行了,这里选择了图中标记的①②④③四条路线,只要在改变其中一条路线的信号灯时同步改变对立面的灯为相同信号就行了。另外还要同时把下一个信号灯切换成相反的信号,例如S2W变红时,同时N2E也要变红,并且E2W或W2E变绿。这里我们选择逆时针方向轮循。
二、系统详细设计
根据业务需求分析,需要对象:信号灯、信号灯控制系统、汽车和路线。下面具体分析每个对象所以属性和方法。
信号灯类(Lamp):信号灯只有红和绿两种状态,用boolean变量表示,true表示绿灯,false表示红灯。还要提供切换信号灯状态的方法turnRed和turnGreen。
信号灯控制系统(LampController):控制系统主要负责在规定时间切换红绿灯,并随着此类的创建,整个系统就开始运作,所以把系统启动的实现放在了构造方法内。
汽车(Vihicles):这里只需要体现汽车穿过路口的过程不需要体现移动细节,也就是捕捉路上减少一辆车的过程,所以,这个车并不需要单独设计成为一个对象,用一个字符串表示就可以了。并且车是属于公路的,应该是一种聚合关系,根据拥有数据者应提供访问数据的方法的规律,这里路要提供增减车辆的方法。
路线(Road):每辆汽车不是看到对面的信号灯变绿就可以穿过的,要按照路线上的车队顺序依次通过路口,这个深有体会,堵车有时两次绿灯都过不去路口。
根据以上分析类图设计如下:
类图很简单,可以看出这三个类之间只是简单的关联, Road中要用到Lamp的信号灯状态判断是否放行车辆,LampController负责定时切换Lamp的信号灯状态。具体实现时为了方便有些方法的功能是放在构造方法里实现的。
三、具体实现
Lamp类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
public enum Lamp {
/**
* E2W=East to West, N2S=North to South
* 从南面的交通灯开始,逆时针执行
*/
//初始状态为红灯
S2N( "N2S" , "S2W" , false ),S2W( "N2E" , "E2W" , false ),
E2W( "W2E" , "E2S" , false ),E2S( "W2N" , "S2N" , false ),
//对立面红灯
N2E( null , null , false ),N2S( null , null , false ),
W2E( null , null , false ),W2N( null , null , false ),
//四个右转方向,始终时绿灯
S2E( null , null , true ),E2N( null , null , true ),
N2W( null , null , true ),W2S( null , null , true );
//灯的状态 true=green,false=red
private boolean lighted;
private String opposite= null ;
private String next= null ;
private Lamp() {}
/**
* @param opposite 对面的灯
* @param nexe 下一个灯
* @param initLighted 灯的初始状态
*/
private Lamp(String opposite,String next, boolean initLighted){
this .opposite=opposite;
this .next=next;
this .lighted=initLighted;
}
//判断灯的状态
public boolean getLighted(){
return lighted;
}
//绿灯亮 同时把对面的灯设为绿 下一个灯设为红灯
public void turnGreen(){
this .lighted= true ;
//如果对面有灯
if (opposite!= null ){
Lamp.valueOf(opposite).turnGreen();
}
}
//红灯亮 对立面的灯也变红
public Lamp turnRed(){
this .lighted= false ;
Lamp nextGreenLamp= null ;
//对面的灯 同步变化
if (opposite!= null ){
Lamp.valueOf(opposite).turnRed();
}
//下一个灯 绿灯亮
if (next!= null ){
nextGreenLamp=Lamp.valueOf(next);
nextGreenLamp.turnRed();
}
return nextGreenLamp;
}
}
|
Road类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
|
public class Road {
//存放每条路上的车辆 车名就表示一辆车
private List<String> vehicles= new ArrayList<String>();
private String roadName= null ;
public Road(String roadName) {
super ();
//根据路的方向取名,名字和对面的红绿灯同名 E2W表示东向西的路
this .roadName = roadName;
//用线程池启动一个线程,随机产生一辆车
Executors.newSingleThreadExecutor().execute( new Runnable(){
@Override
public void run() {
for ( int i= 1 ;i< 1000 ;i++){
try {
//每隔1~10秒 随机产生一辆车
Thread.sleep(( new Random().nextInt( 10 )+ 1 )* 1000 );
} catch (InterruptedException e) {
e.printStackTrace();
}
//访问外部类的成员变量
vehicles.add(Road. this .roadName+ "路 第 " +i+ " 辆车" );
}
}
});
/*
* 定义一个计时器 使这条路每隔1s 就检查一次这条路对应的交通灯的状态
* 如果是绿灯 就每隔1s使离一辆车
*/
ScheduledExecutorService timer=Executors.newScheduledThreadPool( 1 );
timer.scheduleAtFixedRate( new Runnable(){
@Override
public void run() {
//先判断这条路上是否有车
if (vehicles.size()> 0 ){
//在判断交通灯状态
boolean lighted=Lamp.valueOf(Road. this .roadName).getLighted();
if (lighted){
//从汽车列表中移除 并提示已通过路口
System.out.println(vehicles.remove( 0 )+ "通过路口。。。" );
}
}
}
}, 1 , 1 , TimeUnit.SECONDS);
}
}
|
LampController类:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
|
//灯控系统
public class LampController {
private Lamp currentLamp;
public LampController() {
super ();
//交通灯系统初始化 第一个运行的S2N turn green
this .currentLamp = Lamp.S2N;
this .currentLamp.turnGreen();
//定时器 每个10s 切换一次信号灯状态
ScheduledExecutorService timer=Executors.newScheduledThreadPool( 1 );
timer.scheduleAtFixedRate( new Runnable(){
@Override
public void run() {
currentLamp=currentLamp.turnRed();
}
}, 10 , 10 , TimeUnit.SECONDS);
}
}
|
运行结果:
四、总结
本题目整体结构很简单,不涉及复杂的设计模式,重点是对业务逻辑的分析,首先要搞明白交通信号灯的运行机制,如果不考虑右转的情况,简答理解就是东西方向和南北方向的车辆交替放行,同方向等待红灯的车辆先放行直行车辆一段时间,然后再放行左转的车辆。在具体实现上有两个难点:其一就是利用线程设置定时器,实时监控每条路上的信号灯状态和模拟随机在各个方向的路上产生一些车辆,控制系统的任务比较简单只需要定时轮流切换信号灯状态。其二是巧妙的把四个方向的信号灯设计成了一个环形链表,控制系统只需要控制一个信号灯,其他3个就有规律的联动运行了。
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持服务器之家。
原文链接:https://blog.csdn.net/dream_goon/article/details/38073009