首先提取下这个问题的关键要素:交通灯,路,车。三者的一种关系是车可以认为是路的“元素”,车的通过和增加都是由路负责管理的。而每一个十字路口的放行与否,都是通过交通灯控制的。路和灯应该是归属的关系,一个十字路口“拥有”一个交通灯系统。
所以我们抽象交通灯这个类,因为向右是永远放行的,所以我们可以忽略向右的这条线路,而相反方向的灯的变化是完全相同的,所以可以抽象为一个管理系统,这样其实一个路口的交通等的状态就只有4种了,而且这四种同一时刻只有一个是放行的状态。
用枚举实现交通灯:
package traffic;
public enum Lamp {
NSStraight, NSTurn, EWStraight, EWTurn;
private boolean green = false;
public boolean isGreen() {
return green;
}
public void lighteOn() {
this.green = true;
System.out.println(this.toString());
}
public void lightOff(){
this.green = false;
}
Lamp nextLamp() {
switch (this) {
case NSStraight:
lightOff();
NSTurn.lighteOn();
return NSTurn;
case NSTurn:
lightOff();
EWStraight.lighteOn();
return EWStraight;
case EWStraight:
lightOff();
EWTurn.lighteOn();
return EWTurn;
case EWTurn:
lightOff();
NSStraight.lighteOn();
return NSStraight;
}
return null;
}
@Override
public String toString(){
switch (this) {
case NSStraight:
return "----------南北方向直行";
case NSTurn:
return "----------南北方向左转";
case EWStraight:
return "----------东西方向直行";
case EWTurn:
return "----------东西方向左转";
}
return null;
}
}
交通灯的轮换相对来说比较独立,和路的耦合不算大,每个路口可以独立于路配备一个交通灯,这里先用线程实现模拟交通灯的切换规则:
package traffic;
public class LampControl implements Runnable{
Lamp NSStraight = Lamp.NSStraight;
Lamp NSTurn = Lamp.NSTurn;
Lamp EWStraight = Lamp.EWStraight;
Lamp EWTurn = Lamp.EWTurn;
Lamp currentLamp = NSStraight;
public Lamp getCurrentLamp() {
return currentLamp;
}
int StraightTime = 10000;//ms
int TurnTime = 10000;
@Override
public void run() {
currentLamp.lighteOn();
while(true){
try {
Thread.sleep(StraightTime);
currentLamp = currentLamp.nextLamp();
Thread.sleep(TurnTime);
currentLamp = currentLamp.nextLamp();
Thread.sleep(StraightTime);
currentLamp = currentLamp.nextLamp();
Thread.sleep(TurnTime);
currentLamp = currentLamp.nextLamp();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
这样在主函数中可以通过独立的线程模拟单独的交通灯切换功能。
接下来模拟十字路口的车辆过往的展示,一个十字路口有一个交通灯系统,抛开向右自由行驶的路线,有8条行车路线,每条路线用一个集合存放这条路线上的车,适当的时候放行。
package traffic;
import java.util.ArrayList;
import java.util.List;
public enum SingleRoad {
NSRoad, SNRoad, NSLRoad, SNLRoad, EWRoad, WERoad, EWLRoad, WELRoad;
int num = 1;
List<Integer> list = new ArrayList<Integer>();
public void addCar() {
this.list.add(num++);
System.out.println(this.toString()+": "+num + "号车正在等待");
}
public void passCar() {
if(this.list.size()>0){
Integer i = this.list.remove(0);
System.out.println(this.toString()+": "+ i + "号车正在过马路");
}
}
@Override
public String toString() {
switch (this) {
case NSRoad:
return "北向南";
case SNRoad:
return "南向北";
case NSLRoad:
return "北向南左";
case SNLRoad:
return "南向北左";
case EWRoad:
return "东向西";
case WERoad:
return "西向东";
case EWLRoad:
return "东向西左";
case WELRoad:
return "西向东左";
}
return null;
}
}
在创建一个Road类管理一个十字路口的情形,随机的往每条线路上增加车辆并等待,当这条线路的控制灯亮的时候,放行这条线路上的车。
package traffic;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
public class Road implements Runnable {
LampControl lc = new LampControl();
List<SingleRoad> listRoads = new ArrayList<SingleRoad>();
SingleRoad NSRoad = SingleRoad.NSRoad;
SingleRoad SNRoad = SingleRoad.SNRoad;
SingleRoad NSLRoad = SingleRoad.NSLRoad;
SingleRoad SNLRoad = SingleRoad.SNLRoad;
SingleRoad EWRoad = SingleRoad.EWRoad;
SingleRoad WERoad = SingleRoad.WERoad;
SingleRoad EWLRoad = SingleRoad.EWLRoad;
SingleRoad WELRoad = SingleRoad.WELRoad;
public Road(LampControl lc) {
this.lc = lc;
listRoads.add(NSRoad);
listRoads.add(NSLRoad);
listRoads.add(SNRoad);
listRoads.add(SNLRoad);
listRoads.add(EWLRoad);
listRoads.add(EWRoad);
listRoads.add(WELRoad);
listRoads.add(WERoad);
}
void method(){
while(true){
Lamp l = lc.getCurrentLamp();
switch (l) {
case NSStraight:
NSRoad.passCar();
SNRoad.passCar();
passTime();
break;
case NSTurn:
NSLRoad.passCar();
SNLRoad.passCar();
passTime();
break;
case EWStraight:
EWRoad.passCar();
WERoad.passCar();
passTime();
break;
case EWTurn:
EWLRoad.passCar();
WELRoad.passCar();
passTime();
break;
}
}
}
private void passTime(){
try {
//一秒过一辆
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
@Override
public void run() {
while (true) {
try {
//1--3秒随机添加一辆车
Thread.sleep((new Random().nextInt(3) + 1) * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
int index = new Random().nextInt(8);
SingleRoad sr = listRoads.get(index);
sr.addCar();
}
}
}
这样当我们实际运行的时候就有三个线程了,一个线程专门负责灯的转换,一个线程专门负责车的添加,一个线程负责灯亮的时候车的放行。
public static void main(String[] args) {
LampControl lc1 = new LampControl();
Road road = new Road(lc1);
new Thread(lc1).start();
new Thread(road).start();
road.method();
}