1. 逻辑分析
1) 有12条线路,先分析由南向北,由南向西,由东向西和由东向南的四条线路,
2) 右行线路不受交通灯控制,其他线路对称
3) 流程:
南—北 绿灯:先走南-北的车,再走南-西的车 西-东:红灯
南—北 红灯 西-东:绿灯:先走西-东的车,再走西南的车
2. 面向对象分析
面向对象的本质:谁拥有数据,谁就拥有对外操作这些数据的方法。
道路
车
灯
车灯管理系统
建立实例情景
1)车在道路上,用集合存储
2)车灯是12个不变的对象,用枚举类型,和路线同名
3)车灯管理系统用来控制交通灯亮灭的时间间隔
4)在实例中定义12个方向的线路,开启交通灯控制系统
3.Road类分析:车存储在路的集合里,路名和车名是一样的。在构造方法里建立一个线程池(只有一个线程),每隔1-10秒把车辆添加到当前绿灯的路上。得到一个定时器连接池(内部只有一个定时器)。每1秒刷新1次,如果该方向上有车?如果该车前边的车灯是绿的,则移除当前方向的第一辆车。
Road练习代码:
package org.it315.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 {
//存储车辆的集合
private List<String> vechicles=new ArrayList<String>();
//路的名字
private String name=null;
public Road(String name)
{
this.name=name;
//建立一个人只有一个 线程的线程池
ExecutorService pool=Executors.newSingleThreadExecutor();
//产生某个方向上一个车的队列
pool.execute(new Runnable(){
public void run() {
String []directions=new String[]{"S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N","S2E","E2N","N2W","W2S"};
int ranWay=new Random().nextInt(12);
for (int i =1; i < 1000; i++) {
try {
//产生一个1-10秒的随机时间
Thread.sleep((new Random().nextInt(10)+1)*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//产生一辆车,添加到集合中
vechicles.add(directions[ranWay]+"_"+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) {
String carName=vechicles.remove(0);//移除第一个元素
System.out.println(carName+" is traversing");//打印该车信息
}
}
}
},
1,
1,
TimeUnit.SECONDS);
}
}
4.Lamp类分析:
@因为交通灯类里确定有12个对象,所以该类用枚举类型。
@枚举出12条线路,其中主控4条线路交通灯的两灭,主控线路控制对称的4条线路,右拐的4条线路恒定为绿灯。
@有三个属性,当前灯的亮灭,对称线路的名称,下一条线路的名称
@构造方法为这三个属性赋值
@对等的操作有三个方法,返回当前灯的状态。把灯点亮。灭掉当前灯,点亮下盏灯,并返回下盏灯的对象。
Lamp编码练习:
package org.it315.interview.traffic;
public enum Lamp {
//主控灯
S2N("N2S",false,"S2W"),S2W("N2E",false,"E2W"),
E2W("W2E",false,"E2S"),E2S("W2N",false,"S2N"),
//被控灯
N2S(null,false,null),N2E(null,false,null),
W2E(null,false,null),W2N(null,false,null),
//右行灯,恒为绿
S2E("N2W",true,"S2E"),E2N("W2S",true,"E2N"),
N2W(null,true,null),W2S(null,true,null);
private Lamp(String opposite,boolean lighted,String next)
{
this.opposite=opposite;
this.lighted=lighted;
this.next=next;
}
//灯是否为绿
private boolean lighted;
//返回灯的状态
public boolean isLighted()
{
return lighted;
}
//把灯变绿
public void light(){
this.lighted=true;
if (opposite!=null) {
Lamp.valueOf(opposite).light();
}
System.out.println(this.name()+"灯绿了!!,下面共有六个方向能看到汽车穿行");
}
//把灯变红
public Lamp blackOut()
{
this.lighted=false;
if (opposite!=null) {
Lamp.valueOf(opposite).blackOut();
}
Lamp ligthNext=null;
if (next!=null) {
ligthNext=Lamp.valueOf(next);
System.out.println("绿灯从"+name()+"-->切换为"+next);
ligthNext.light();
}
return ligthNext;
}
//与灯同时为绿的对应方向
private String opposite;
//灯变红时下一个变绿的灯
private String next;
}
5.LampController逻辑分析
@有一个当前线路的属性
@在构造方法中初始化最开始的线路,并点亮改方向上的灯。
@每隔XX调用灭灯的方法,返回下一盏灯的对象
@如果直行线,和拐弯可以时间分段是不是更好?时间比较紧,代码存在问题
package org.it315.interview.traffic;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class LampController {
private Lamp currentLamp;//定义一个当前灯的对象
private int i=0;//定义一个全局运行变量,用来控制代码块的执行
public LampController()
{
currentLamp=Lamp.S2N;
currentLamp.light();//初始化最开始亮的灯
ScheduledExecutorService timer=Executors.newScheduledThreadPool(2);
while(true)
{
if (i%2==0) {
timer.schedule(new Runnable()//开启偶数时间段进程
{
public void run() {
currentLamp=currentLamp.blackOut();
}
},
5,
TimeUnit.SECONDS);
System.out.println("你好,我停了5秒");
}else {
timer.schedule(new Runnable()//开启奇数时间段进程
{
public void run() {
currentLamp=currentLamp.blackOut();
}
},
2,
TimeUnit.SECONDS);
System.out.println("你好,我停了2秒");
}
i++;
}
}
}
思考:if块内的定时器不被主线程打断的话,程序就能正常执行,可是怎么做呢?求指教
6.MainClass分析
@定义一个线路名称的数组,匿名实例化线程对象
@匿名实例化LampController对象,在其构造方法内直接运行交通灯控制的方法。
package org.it315.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"};
//Road循环实例对象
for (int i = 0; i < directions.length; i++) {
new Road(directions[i]);
}
//实例化交通灯管理系统
new LampController();
}
}
总结:多谢代码多分析,学到高人的1/10就心满意足了。