package com.isoftstone.interview.traffic;
//因为灯的所有状态是可以确定的,并且灯之间的关系也是确定的,故将灯定义为枚举类
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),N2W(null,null,true),E2N(null,null,true),W2S(null,null,true);
//用灯的亮灭代表红绿灯
private boolean lighted;
//定义一个属性代表与当前灯相对应的灯
private String opposite;
//定义一个next属性代表当前灯的下一个灯,即当前灯熄灭以后下一个该点亮的灯
private String next;
//枚举类的构造方法必须为私有,通过构造器可以传入灯对象的对应灯与下一个灯的属性,因此灯之间的关系在创建时就确
//定了
private Lamp(String opposite,String next,boolean lighted ){
this.opposite=opposite;
this.next=next;
this.lighted=lighted;}
private Lamp(){
}
//判断灯是否点亮并返回其状态
public boolean isLighted(){
return lighted;
}
//熄 灯方法,将当前灯和当前灯的对应灯熄灭并会返回当前灯的下一个灯
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;
}
//开灯方法,将当前灯和其对应灯点亮
public void Light(){
this.lighted=true;
if(opposite!=null){
Lamp.valueOf(opposite).Light();
}
System.out.println(name() + " 转为绿灯,下面总共应该有6个方向能看到汽车穿过!");
}
}
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(){
currentLamp=Lamp.S2N;
currentLamp.Light();
ScheduledExecutorService timer=Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
new Runnable(){
public void run(){
System.out.println("开始运作");
currentLamp.BlackOut();
}
},
10,
10,
TimeUnit.SECONDS);
}
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<String> vehicle=new ArrayList<>();
//定义路的名字,这里的名字主要是指路上车的行车方向
private String name=null;
//定义类Road类的构造器,传入一个name属性,并初始化
public Road( String name){
this.name=name;
//使用Executros工厂产生一个单线程线程池pool,该线程池中传入的Runnable模拟不断有车开到路上的情景。
//当路上的车小于1000辆时,通过线程的休眠来实现每隔一段时间(10秒以内)向路下增加一辆车
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)*1000);}
catch(InterruptedException e){
e.printStackTrace();
}
vehicle.add(Road.this.name+"_"+i);
}
}
});
/*定义一个延迟执行的线程池timer,模拟当绿灯亮时每隔一段时间就让一辆车,这里是的时
间间隔是1秒**/
ScheduledExecutorService timer=Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
new Runnable(){
public void run(){
if(vehicle.size()>0){
boolean lighted=Lamp.valueOf(Road.this.name).isLighted();
if(lighted){
System.out.println(vehicle.remove(0)+"is travelling");
}
}
}
},
1,
1,
TimeUnit.SECONDS);
}
}
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","W2N","S2E","E2N","N2W","W2S"};
for(int i=0;i<directions.length;i++){new Road(directions[i]);}
new LampController();
}
}
首先就是一个细节问题,就是Controller中的Run()方法应该是每十秒执行一次没错的,但是我照这代码执行的时候我好像只看到run()方法中的语句只执行了一次,后来我参考了老师的代码修改了一下其实就修该了Lamp类中点灯方法那个nxetLamp那里,我原来是在没判断nextLamp是否为null时就先把Lamp.valueOf(Lamp)附了给nextLamp,然后在nextLamp中直接调用Light方法,其实我认为这个虽然逻辑上有点怪,但无论如何定时器的运行是不会错的呀,输出语句怎么才运行一次呢;第二个问题就是关于为什么要把LampController单独封装成一个类,其实把它放在Lamp类中作为一个类方法这么做是不好还是不行? |