模拟实现十字路口的交通灯管理系统逻辑,具体需求如下:
异步随机生成按照各个路线行驶的车辆。
例如:
由南向而来去往北向的车辆 ---- 直行车辆
由西向而来去往南向的车辆 ---- 右转车辆
由东向而来去往南向的车辆 ---- 左转车辆
。。。
信号灯忽略黄灯,只考虑红灯和绿灯。
应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。
具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。
注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。
每辆车通过路口时间为1秒(提示:可通过线程Sleep的方式模拟)。
随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置。
不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。
总共12条线路,可以假设每条路都有一个红绿灯控制器,右转弯的四条路线可以设置为常绿.另外其他八条线路都是两两成对的,可以归为四组.所以只考虑对应四条线路,其相反方向的线路跟随这四条线路切换,不必额外考虑.
Road类的编写
设计一个Road类表示线路, 每个Road对象代表一条路线,总共有12条路线,即产生12个实例对象.构造方法包含不断在该路上增加车的方法和遇到路灯可通过从而减少车辆的方法.
package likai.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; class Road { private List<String> vechicles = new ArrayList<String>(); private String name; 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 { Thread.sleep(new Random().nextInt(10)+1); } catch (InterruptedException e) {e.printStackTrace();} vechicles.add(Road.this.name+"的第"+i+"辆车"); } } }); //创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。 ScheduledExecutorService timer = Executors.newScheduledThreadPool(1); //每隔1秒干这件事 timer.scheduleAtFixedRate(new Runnable(){ @Override //移走集合中的第一辆车 public void run() { if(vechicles.size()>0){ boolean lighted = Lamp.valueOf(Road.this.name).isLighted(); //假如灯是亮的 if(lighted){ System.out.println(vechicles.remove(0)+"通过了路口"); } } } },1,1, //说明前面数字的度量单位 TimeUnit.SECONDS); } }
Lamp枚举的编写
灯为枚举类,提供给LampController使用.因为是一个十字路口,所以必须设计12个灯, 十字路口的四个路口的每个路口使用三盏灯,以南为例.南往西,南往北,南往东.
每个枚举元素各表示一个方向的控制灯
下面元素表示与上面的元素的相反方向的灯,它们的“相反方向灯”和“下一个灯”应忽略不计!
由南向东和由西向北等右拐弯的灯不受红绿灯的控制,所以,可以假想它们总是绿灯
package likai.traffic; //灯为枚举类,提供给LampController使用 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 String opposite; private String next; private boolean lighted ; private Lamp(){} private Lamp(String opposite, String next, boolean lighted){ this.opposite = opposite; this.next = next; this.lighted = lighted; } public boolean isLighted(){ return lighted ; } public void light(){ this.lighted = true; //有对应的灯,才随之变化 if(opposite !=null) Lamp. valueOf(opposite).light(); System. out.println(name() + "灯变绿,下面总共应该有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; } }
LampController控制器的编写
该类的编写比较简单,只要在构造方法中设置初始状态时南往北的灯为绿,再设计一个线程池里只有一个线程每隔6秒让下一个灯变绿操作即可.
package likai.traffic; import java.util.concurrent.Executors; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.TimeUnit; class LampController { private Lamp currentLamp; public LampController(){ currentLamp = Lamp.S2N ; currentLamp.light(); //每隔6秒让下一个灯变绿 ScheduledExecutorService timer = Executors.newScheduledThreadPool(1); timer.scheduleAtFixedRate( new Runnable(){ public void run(){ System. out.println("-------路灯开始变换------" ); currentLamp = currentLamp.blackOut(); } },6,6,TimeUnit. SECONDS); } }
MainClass函数的编写.
利用枚举类,建立12条线路,每条线路包含的信息包括对面灯的标志,下个灯的标志,以及灯的状态.再实例化一个控制器即可.
package likai.traffic; public class MainClass { public static void main(String[] args) { System. out.println("--Traffic System--" ); String[] directions = new String[]{ "S2N","S2W" ,"E2W" ,"E2S" ,"N2S" ,"N2E" ,"W2E" ,"W2N" ,"S2E" ,"E2N" ,"N2W" ,"W2S" }; //产生12条路 for(int i=0;i<directions .length ;i++){ new Road(directions[i]); } new LampController(); } }
打印结果:
--Traffic System-- N2S灯变绿,下面总共应该有6个方向能看到汽车穿过! S2N灯变绿,下面总共应该有6个方向能看到汽车穿过! N2S的第1辆车通过了路口 S2N的第1辆车通过了路口 E2N的第1辆车通过了路口 S2E的第1辆车通过了路口 W2S的第1辆车通过了路口 N2W的第1辆车通过了路口 S2N的第2辆车通过了路口 N2S的第2辆车通过了路口 S2E的第2辆车通过了路口 E2N的第2辆车通过了路口 N2W的第2辆车通过了路口 W2S的第2辆车通过了路口 S2N的第3辆车通过了路口 N2S的第3辆车通过了路口 S2E的第3辆车通过了路口 W2S的第3辆车通过了路口 N2W的第3辆车通过了路口 E2N的第3辆车通过了路口 S2N的第4辆车通过了路口 N2S的第4辆车通过了路口 S2E的第4辆车通过了路口 E2N的第4辆车通过了路口 W2S的第4辆车通过了路口 N2W的第4辆车通过了路口 S2N的第5辆车通过了路口 N2S的第5辆车通过了路口 E2N的第5辆车通过了路口 S2E的第5辆车通过了路口 W2S的第5辆车通过了路口 N2W的第5辆车通过了路口 S2N的第6辆车通过了路口 -------路灯开始变换------ 绿灯从S2N切换为S2W N2E灯变绿,下面总共应该有6个方向能看到汽车穿过! S2W灯变绿,下面总共应该有6个方向能看到汽车穿过! N2E的第1辆车通过了路口 N2S的第6辆车通过了路口 S2E的第6辆车通过了路口 ...... ......