交通灯控制系统面试题。
------- 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 }