------- android培训、java培训、期待与您交流! ----------
一、
交通灯管理系统
模拟实现十字路口的交通灯管理系统逻辑,具体需求如下:
异步随机生成按照各个路线行驶的车辆。例如:由南向而来去往北向的车辆 ---- 直行车辆由西向而来去往南向的车辆 ---- 右转车辆由东向而来去往南向的车辆 ---- 左转车辆。。。
信号灯忽略黄灯,只考虑红灯和绿灯。
应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。
具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。
每辆车通过路口时间为1秒(提示:可通过线程Sleep的方式模拟)。
随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置。
不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。
二、分析
总共有
12
条路线,为了统一编程模型,可以假设每条路线都有一个红绿灯对其进行控制,右转弯的
4
条路线的控制灯可以假设称为常绿状态,另外,其他的
8
条线路是两两成对的,
可以归为
4
组,所以,
程序只需考虑图中标注了数字号的
4
条路线的控制灯的切换顺序,这
4
条路线相反方向的路线的控制灯跟随这
4
条路线切换,不必额外考虑。
红绿灯的控制系统,汽车,路线。汽车看到自己所在路线对应的灯绿了就穿过路口吗?不是,还需要看其前面是否有车,看前面是否该有增加车辆和减少车辆的方法了。再看题目,我们这里并不要体现车辆移动的过程,只是捕捉出车辆穿过路口的过程,也就是捕捉路上减少一辆车的过程,所以,这个车并不需要单独设计成为一个对象,用一个字符串表示就可以了。
三、代码
1、Road 类
每个Road对象都有一个name成员变量来代表方向,有一个vehicles成员变量来代表方向上的车辆集合。在Road对象的构造方法中启动一个线程每隔一个随机的时间向vehicles集合中增加一辆车(用一个“路线名_id”形式的字符串进行表示)。在Road对象的构造方法中启动一个定时器,每隔一秒检查该方向上的灯是否为绿,是则打印车辆集合和将集合中的第一辆车移除掉。
package com.isoftstone.interview.traffic;import java.util.*;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.ScheduledExecutorService;import java.util.concurrent.TimeUnit;
public class Road {//为了面向接口编程使用List而不是ArrayListprivate List<String> vechicles = new ArrayList<String>();//定义路的名字private String name = null ;//路public Road(String name){this . name = name;ExecutorService pool = Executors. newSingleThreadExecutor ();//调用execute函数,给线程池提交一个任务pool.execute( new Runnable(){public void run() {//产生车for ( int i=1;i<1000;i++){try {Thread. sleep (( new Random().nextInt(10) + 1) * 1000);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}//向路上添加车vechicles .add(Road. this . name + "_" + i);}}});//定义一个定时器ScheduledExecutorService timer = Executors. newScheduledThreadPool (1);timer.scheduleAtFixedRate(new Runnable(){public void run(){if ( vechicles .size()>0){ //如果路上有车boolean lighted = Lamp. valueOf (Road. this . name ).isLighted();if (lighted){ //如果灯亮System. out .println( vechicles .remove(0) + " is traversing !" );}}}},1, //指定过多长时间去执行run()1, //执行完以后,再过多场时间继续执行run()TimeUnit. SECONDS ); //时间单位}}
2、Lamp类
系统中有
12
个方向上的灯,在程序的其他地方要根据灯的名称就可以获得对应的灯的实例对象,综合这些因素,将
Lamp
类用
java5
中的枚举形式定义更为简单。
每个Lamp对象中的红、绿状态用lighted变量表示,选用S2N、S2W、E2W、E2N这四个方向上的Lamp对象依次轮询变亮,Lamp对象中还要有一个opposite变量来表示它们相反方向的灯, 再用一个next变量来表示此灯变绿后的下一个变绿的灯。这三个变量用构造方法的形式进 行赋值,因为枚举元素必须在定义之后引用,所以无法再构造方法中彼此相互引用,所以,
相反方向和下一个方向的灯用字符串形式表示。
增加让Lamp变绿和变红的方法:getGreen和getRed,对于S2N、S2W、E2W、E2N这四个方向上 的Lamp对象,这两个方法内部要让相反方向的灯随之变绿和变红,getRed方法还要让下一个 灯变绿。
除了S2N、S2W、E2W、E2N这四个方向上的Lamp对象之外,其他方向上的Lamp对象的 next和opposite属性设置为null即可,并且S2N、S2W、E2W、E2N这四个方向上的Lamp对象的next和opposite属性必须设置为null,以便防止getGreen和getRed进入死循环。
package com.isoftstone.interview.traffic;/***
* @author Administrator**/public enum Lamp {//每个枚举元素各表示一个方向的控制灯//南北, 南西, 东西, 东南S2N ( "N2S" , "S2W" , false ), S2W ( "N2E" , "E2W" , false ), E2W ( "W2E" , "E2S" , false ), E2S ( "W2N" , "S2N" , false ),N2S ( null , null , false ), N2E ( 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 );private Lamp(){};private Lamp(String opposite,String next, boolean lighted){this . opposite = opposite;this . next = next;this . lighted = lighted;}//灯的状态private boolean lighted ;//对应的灯的名字。private String opposite ;//下一个变绿的灯private String next ;public boolean isLighted(){return lighted ;}//灯变亮public void light(){this . lighted = true ;if ( opposite != null ){Lamp. valueOf ( opposite ).light();}System. out .println(name() + " lamp is greem, 下面总共看到6个方向的车通过" );}//灯变黑public Lamp blackOut(){this . lighted = 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;}}
3、
LampController类
整个系统中只能有一套交通灯控制系统,所以,LampController类最好是设计成单例。
LampController构造方法中要设定第一个为绿的灯。
LampController对象的start方法中将当前灯变绿,然后启动一个定时器,每隔10秒将当前灯变红和将下一个灯变绿
package com.isoftstone.interview.traffic;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class LampController {
//当前的灯
private Lamp currentLamp;
public LampController(){
this.currentLamp = Lamp.S2N;
this.currentLamp.light();
//定义定时器
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
new Runnable(){
public void run(){
//System.out.println("来了");
currentLamp = currentLamp.blackOut();
}
},
10,
10,
TimeUnit.SECONDS);
}
}
4、测试类
package com.isoftstone.interview.traffic;
public class MainClass {public static void main(String[] args){String[] directions = new String[]{"S2N" , "S2W" , "E2W" , "E2S" , "N2S" , "N2E" , "W2E" , "W2M" , "S2E" , "E2N" , "N2W" , "W2S"};for ( int i=0;i<directions. length ;i++){new Road(directions[i]);}new LampController();}}