要求:
异步随机生成按照各个路线行驶的车辆。
例如:
由南向而来去往北向的车辆 ---- 直行车辆
由西向而来去往南向的车辆 ---- 右转车辆
由东向而来去往南向的车辆 ---- 左转车辆
信号灯忽略黄灯,只考虑红灯和绿灯。
应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。
具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。
注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。
?每辆车通过路口时间为1秒(提示:可通过线程Sleep的方式模拟)。
?随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置。
?不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。
分析:
总共有12条线路。直行4条,左转4条,右转4条。
编程模式:每条线路都控制一个交通灯,右转的等是常绿的。南北,东西是对应的。只考虑南—>北,南—>西,东—>西,东—>南,四条线路。
对象和类的设计:总共有三个类
Lamp枚举类:有12个灯,创建对象很麻烦,考虑使用枚举来设计,右转的等设计为常绿,其余八个等设计为4组。每个枚举元素包含oppsite方向的灯,下一个亮的等next(),
灯是否是亮的isLighting()三个属性。
三个方法:
isLighting():灯是否是亮的
lightToGreen():灯变绿,某个灯变绿时,对面的灯也变绿,某个等变红时;
lightToRed():灯变红,对面的等也变红,同时下一个等变绿。
public enum Lamp {/**
* Lamp类:
* 因为有12个lamp对象,而且需要频繁的被调用,new对象很麻烦,所以使用枚举。
* 该枚举:两个构造方法,三个方法
* 三个成员变量:
* 1.对面的灯:oppositeLamp
* 2.下一个灯:nextLamp
* 3.亮灯的标志:flag
* 两个构造方法:
* 1.空参数方法
* 2.三个参数的构造方法,接受上面的三个变量
* 三个方法:
* 1.isLighting():用于判断灯的状态,true绿灯,false代表红灯
* 2.toGreen();灯变绿的方法,同时将对面的灯变绿
* 3.toRed();灯变红的方法,同时将对面的灯变红,并返回下一个灯(给控制器用)
*
*/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),N2W("null","null",true),E2N("null","null",true),W2S("null","null",true);
private String oppositeLamp;
private String nextLamp;
private boolean lighting;
private Lamp(){}
private Lamp(String oppositeLamp,String nextLamp,boolean lighting){
this.oppositeLamp=oppositeLamp;
this.nextLamp=nextLamp;
this.lighting=lighting;
}
public boolean isLighting(){
return lighting;
}
//灯变绿,同时将对面的等变绿
public void toGreen(){
this.lighting=true;
if(oppositeLamp!=null){
Lamp.valueOf(oppositeLamp).toGreen();
}}
//灯变红,将对面的灯变红,同时将下一个灯变绿
public Lamp toRed(){
this.lighting=false;
if(oppositeLamp!=null){
Lamp.valueOf(oppositeLamp).toRed();
}
Lamp next =null;
if(nextLamp!=null){
Lamp.valueOf(nextLamp).toGreen();
next = Lamp.valueOf(nextLamp);
}
return next;
}
}
Road类:
12条路线都有名字。Road查看交通灯,如果是绿灯就放行。车辆vehicles设计成有road来生成。路线的名字就是对应的灯的名字。
在构造函数中创建两个线程:一个控制产生车辆,一个控制放行车辆。
import java.util.LinkedList;
import java.util.Random;
import java.util.concurrent.Executors;
public class Road {/** road类:
* 功能:产生车辆,并根据交通灯放行车辆。
* 注:
* 1.使用LinkedList模拟车辆产生和放行
* 2.在构造方法中,创建两个线程。不再创建别的方法,是因为路一旦存在,就让它运行
* 3.路一初始化就要有名字,同时该名字也是其对应灯名字。在判断灯的红绿时,很方便。
*/
private String name;
LinkedList<String> link = new LinkedList<String>();
Road(String name){
this.name=name;
//创建产生的车辆的线程,使用线程工具类,创建一个线程池
Executors.newScheduledThreadPool(1).execute(new Runnable(){
public void run() {
for(int x=0;x<1000;x++){
link.offerFirst(Road.this.name+x+"号车辆");
//每隔1-10秒产生一辆车
int randomNum = new Random().nextInt(10)+1;
try {
Thread.sleep(randomNum*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}});
//创建线程,放行车辆
Executors.newFixedThreadPool(1).execute(new Runnable(){
public void run() {
//路的名字就是灯的名字
boolean flag = Lamp.valueOf(Road.this.name).isLighting();
if(flag==true){
link.pollLast();
}}
});
}
}
LampController类
成员变量:当前的灯
方法:控制灯的方法。
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
public class LmapController {/**
* 该类的功能:每隔10秒让灯变红,注意:只是让它控制变红,不用控制变绿,因为变红的同时Lamp会将下一个等变绿、
* 有一个成员:currentLamp
* 一个构造方法:创建改变灯的线程
*/
private Lamp currentLamp=Lamp.S2N;
LmapController(){
currentLamp.toGreen();//默认第一个灯是绿灯
//创建调度线程,10秒之后变换
Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
new Runnable(){
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
currentLamp=currentLamp.toRed();}
},
10,
10,
TimeUnit.SECONDS
);
}
}
Main方法:
public class Mian {
public static void main(String[] args) {
String[] directions = {"S2N","S2W","E2W","E2S",
"N2S","N2E","W2E",
"W2N","S2E","N2W","E2N","W2S"};
//new12个对象
for(int x=0;x<12;x++){
new Road(directions[x]);
}
new LampController();
}}