交通灯控制系统面试题。
------- android培训、java培训、期待与您交流! ----------
模拟实现十字路口的交通灯管理系统逻辑,具体需求如下:
异步随机生成按照各个路线行驶的车辆。
例如:
由南向而来去往北向的车辆 ---- 直行车辆
由西向而来去往南向的车辆 ---- 右转车辆
由东向而来去往南向的车辆 ---- 左转车辆
。。。
信号灯忽略黄灯,只考虑红灯和绿灯。
应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。
具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。
注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。
每辆车通过路口时间为1秒(提示:可通过线程Sleep的方式模拟)。
随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置。
不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。
看了一遍张老师的视频。主要借鉴了枚举。其他地方都是自己完成的。
但是程序跑起来cpu消耗还是挺高。不知如何优化。
1 import java.util.*;
2 public class Traffic{
3 public static void main (String[] args){
4 //定义一个字典,准备用来建立Road对象,不然会搞死人
5 String[] dics = {"S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N","S2E","E2N","N2W","W2S"};
6 //两句话建立12个road对象,爽
7 for(int i = 0; i <dics.length;i++){
8 new Road(dics[i]);
9 }
10 //建立交通灯控制对象
11 LampController lc = new LampController();
12 //设置初始灯为S2N
13 Lamp currentLamp = Lamp.S2N;
14 //交通灯控制对象在主线程中
15 while (true){
16 //每11秒对把当前的绿灯关闭,返回下一组灯。
17 mySleep(11000);
18 currentLamp = lc.offLamp(currentLamp);
19 }
20 }
21 //避免多次try catch,定义一个mysleep方法。
22 public static void mySleep(long millinSec){
23 try {
24 Thread.sleep(millinSec);
25 }
26 catch(Exception e){
27 }
28 }
29 }
30 //交通灯控制,很简单,就一个方法,关闭灯。
31 class LampController{
32 Lamp Lamp;
33 LampController(){
34 }
35 Lamp offLamp(Lamp lamp){
36 return lamp.setBlank();
37 }
38 }
39
40 class Road{
41 private String name= null;
42 //因为是先进先出,所以只适用列表的头和尾,所以使用LinkedList,另外加上同步代码保证线程安全。
43 private List<Integer> cars = Collections.synchronizedList( new LinkedList<Integer>());
44 //一生成Road对象,就开始来车和车通过的线程。
45 Road(String name){
46 this.name =name;
47 Thread t1 = new Thread(new RoadAddCar(name, cars));
48 Thread t2 = new Thread(new RoadCarPass(name, cars));
49 t1.start();
50 t2.start();
51 }
52 }
53 //实现Runnable接口,准备来车的线程
54 class RoadAddCar implements Runnable{
55 //定义使用到的变量,用于构造函数和打印结果。
56 private String name ;
57 private Integer carID = 1;
58 private List<Integer> cars;
59 //传入路名和车的队列。
60 RoadAddCar(String name,List<Integer> cars){
61 this.name = name;
62 this.cars = cars;
63 }
64 public void run(){
65 while (true){
66 //0.5秒-2.5秒时间,随机来车。来一辆车就打印一次。
67 cars.add(carID);
68 System.out.println(name+"来车ID:" + carID);
69 carID = carID + 1;
70 Traffic.mySleep((long)(Math.random()*2000 + 500));
71 }
72 }
73
74 }
75 //实现Runnable,准备车通行的线程
76 class RoadCarPass implements Runnable{
77 private List<Integer> cars;
78 private String name ;
79 private Integer carID;
80 //构造函数传入路名和车的队列。
81 RoadCarPass(String name,List<Integer> cars){
82 this.name = name;
83 this.cars = cars;
84 }
85 public void run (){
86 while (true){
87 //如果绿灯则考虑通行
88 if (Lamp.valueOf(name).isLighted()){
89 //当然这条路还得有车才行。
90 if (cars.size() > 0){
91 carID = cars.remove(0);
92 //因为是只有花1秒时间通过了路口,才会打印结果,所以会在运行结果中看到,红灯亮了,车才通过。
93 //因为Lamp.setBlank()中,红灯亮了,过1秒之后,下组灯的绿灯才会亮,所以不会出现交通事故。
94 Traffic.mySleep(1000);
95 System.out.println(" "+name+"路,ID:"+carID+"通过路口,耗时1000毫秒");
96 }
97 }
98 //因为如果此路口是红灯,则上述判断不成立,如果下面不休息,系统资源消耗过大。
99 else
100 Traffic.mySleep(1000);
101 }
102 }
103 }
104 //枚举,虽然在基础视频上没有讲,但这两个面试题,让我觉得枚举很有用。这个题目做完之后,对枚举的认识有提高了。
105 enum Lamp{
106 //定义了每个灯所对应的灯和下一个灯,默认为红灯。
107 S2N("N2S","S2W",false), S2W("N2E","E2W",false), E2W("W2E","E2S",false), E2S("W2N","S2N",false),
108 N2S("S2N","N2E",false), N2E("S2W","W2E",false), W2E("E2W","W2N",false), W2N("E2S","N2S",false),
109 //右转的路的都为绿灯
110 S2E(null,null,true), E2N(null,null,true), N2W(null,null,true), W2S(null,null,true);
111 private String opposite = null;
112 private String next = null;
113 private boolean lighted = false;
114 //Lamp对象的构造方法。
115 Lamp(String opposite,String next,boolean lighted){
116 this.opposite = opposite;
117 this.next = next;
118 this.lighted = lighted;
119 }
120 public boolean isLighted(){
121 return this.lighted;
122 }
123 public String nextLamp(){
124 return this.next;
125 }
126 //开绿灯,打印到控制台
127 private void setL(Lamp lamp){
128 lamp.lighted = true;
129 System.out.println("== "+lamp.name() + "路绿灯亮,车辆可以通过");
130 }
131 private void setLight(){
132 //一次开2个绿灯,比感觉比递归更容易让人理解
133 setL(this);
134 setL(valueOf(this.opposite));
135 }
136 //开红灯,打印到控制台
137 private void setO(Lamp lamp){
138 lamp.lighted = false;
139 System.out.println("XX "+lamp.name() + "路红灯亮,车辆停止");
140 }
141 public Lamp setBlank(){
142 //一次开2个红灯,比感觉比递归更容易让人理解
143 setO(this);
144 setO(valueOf(this.opposite));
145 //因为车辆通过需时1秒,所以在红灯亮了之后1s,才打开下一轮灯的绿灯。
146 Traffic.mySleep(1000);
147 valueOf(this.next).setLight();
148 return valueOf(this.next);
149 }
150 }

浙公网安备 33010602011771号