交通灯控制系统面试题。

------- 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 }

 

 

posted @ 2012-12-28 18:47  qinbin  阅读(460)  评论(0编辑  收藏  举报