黑马程序员-Java项目之交通灯管理系统


1、需求分析

模拟实现十字路口的交通灯管理系统逻辑,具体需求如下:
 
异步随机生成按照各个路线行驶的车辆。
例如:
由南向而来去往北向的车辆 ---- 直行车辆
由西向而来去往南向的车辆 ---- 右转车辆
由东向而来去往南向的车辆 ---- 左转车辆
。。。
信号灯忽略黄灯,只考虑红灯和绿灯。
应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。
具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。
注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。
每辆车通过路口时间为1秒(提示:可通过线程Sleep的方式模拟)。
随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置。

不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。

2、项目分析图


java红绿灯模拟 用java编写红绿灯_System



3、从面向对象的角度分析

1)交通灯:因为只考虑红绿灯,因此只需控制直行的灯和左转的灯即可,而对侧的路口显示的是相同的灯,因此主要只需控制相邻两个方向上直行和左转共四个交通灯的变化即可,右转灯为常绿。其内部所具备的功能是亮灯的状态、灯变绿、灯变红

2)路口:控制着车辆的存在与消失,12个方向均可又车等候或行驶。

3)车辆:因为每一个路口等候的车都是有顺序的,在灯变绿后,排在前面的车先移除,因此用ArrayList集合存储车辆。

4、程序代码:

1)交通灯:

package com.itheima.traffic;//定义交通灯的枚举类
public enum Lamp {
//12个方向,与每个灯相关的属性是对面的灯、下一个灯、当前灯状态
S2N("N2S","S2W",false),S2W("N2E","W2E",false),W2E("E2W","W2N",false),W2N("E2S","S2N",false),
N2S(null,null,false),N2E(null,null,false),E2W(null,null,false),E2S(null,null,false),
S2E(null,null,true),W2S(null,null,true),N2W(null,null,true),E2N(null,null,true);
private String opposite;
private String next;
private boolean flag;
//初始化时,可传入一个方向的交通灯状况
private Lamp(String opposite,String next,boolean flag){
this.opposite=opposite;
this.next=next;
this.flag=flag;
}
//定义功能,判断当前灯状态
public boolean isLighted(){
return flag;
}
//定义功能,开启当前灯、对面灯
public void light(){
this.flag = true;
if(opposite!=null){
Lamp.valueOf(opposite).light();
}
System.out.println(name()+"is green");
}
//定义功能,关闭当前灯、对面灯,开启下一个灯
public Lamp blackOut(){
flag = false;
if(opposite!=null){
Lamp.valueOf(opposite).blackOut();
}
Lamp nextLamp = null;
if(next!=null){
nextLamp = Lamp.valueOf(next);
System.out.println("绿灯从"+name()+"切换到"+next);
nextLamp.light();
}
return nextLamp;
}
}

2)交通灯控制器:

package com.itheima.traffic; 
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
//交通灯控制器
public class LampController {
public Lamp currentLamp ;
//初始化灯为S2N
public LampController(){
currentLamp = Lamp.S2N;
currentLamp.light();
//定义线程池,该线程池的主要功能是控制每隔10秒变化一次灯
//该线程池,它可安排在给定延迟后运行命令或者定期地执行。
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
new Runnable(){
public void run (){
currentLamp = currentLamp.blackOut();
}
},
10,//初始延迟10秒
10,//周期,每隔10秒变化一次
TimeUnit.SECONDS
);
}
}
 
 
 
3)十字路口,控制车辆:
package com.itheima.traffic; 
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
 
//控制路上的车辆
//12个方向上均可有等候的车辆,定义容器存储车辆,并根据交通灯的状态按先后顺序移除
public class Road {
//定义车辆的集合,存储某个方向上的某辆车
private List<String> vehicles = new ArrayList<String>();
private String name = null;
//随机生成车辆,存入集合
public Road(String name){
this.name = name;
ExecutorService pool = Executors.newSingleThreadExecutor();
pool.execute(new Runnable(){
public void run(){
for(int i=1;i<1000;i++){
try {
//随机1-10秒内产生一辆车
Thread.sleep((new Random().nextInt(10)+1)*1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
vehicles.add(Road.this.name+"_"+i);
System.out.println(Road.this.name+"_"+i+"::is waiting");
}
}
});
//定义线程池,判断当前灯的状态,如果为绿灯,该方向上的车依次移除
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
new Runnable(){
public void run(){
if(vehicles.size()>0){
boolean light = Lamp.valueOf(Road.this.name).isLighted();
if(light){
System.out.println(vehicles.remove(0)+"::is moving");
}
}
}
}, 
1,
1, 
TimeUnit.SECONDS);
}
}

4)主函数:

package com.itheima.traffic; 
public class Main {
 
public static void main(String[] args) {
//定义12个方向的数组
String[] names = {"S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N","S2E","E2N","N2W","W2S"};
for(int i=0;i<names.length;i++){
new Road(names[i]);
}
new LampController();
}
}


5、项目总结



通过本次项目学习,学习到了枚举的具体用法,同时更加深刻地理解了Java面向对象的设计思想。Java的 java.util.concurrent.*包中有许多优秀的线程启动方式、任务调度以及lock显示锁机制等,学无止境。