您的位置:首页 > 职场人生

黑马程序员_7K月薪面试题交通灯管理系统

2015-04-20 15:34 555 查看
-----Java培训、Android培训、iOS培训、.Net培训、期待与您交流!-----

今天花一上午学习了张老师关于交通灯管理系统的视频,不得不说老师讲的是在是好,老师也是一般人,也是通过一步步来实现的,coding中也会遇到bug,老师不仅示范了整个项目从创建,到面向对象的思想:“谁有数据,谁就对外提供操作这届数据的方法。”。还有

原始需求:

模拟实现十字路口的交通灯管理系统逻辑,具体需求如下:

异步随机生成按照各个路线行驶的车辆。

例如:

由南向而来去往北向的车辆 ---- 直行车辆

由西向而来去往南向的车辆 ---- 右转车辆

由东向而来去往南向的车辆 ---- 左转车辆

。。

信号灯忽略黄灯,只考虑红灯和绿灯。

应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。

具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。

注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。

每辆车通过路口时间为1秒(提示:可通过线程Sleep的方式模拟)。

随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置。

不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。

首先对题目进行解读:

通过结合实际,知道在十字路口,每个方向的车可以有三种选择,如由南来的车可以向北,向东,向西走,如此便有12条路线。

再每个方向向右拐的车不受红绿灯影响,如此便只考虑8条路线。再当有车南来北网时,此时也有车北来难往;有车由南向西拐时,此时也有车由北向东拐,如此,只需要考虑4条路线。

现在定为:由南向北(S2N),由南向西(N2W),由东向西(E2W),由东向南(E2S)。

然后视频中从面向对象的角度选择了几个典型的对象:

1,Road(路)

2,Lamp(红绿灯)

3,LampController(灯控制器)

4,MainClass(测试类)

Road拥有创建车和移除车的方法,Lamp代表红绿灯,具有转换颜色的方法,灯控制器能循环控制各个方向上的灯的循环开关

1,Road类

package com.traffic;

import java.util.ArrayList;
import java.util.List;
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;
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(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
vechicles.add(Road.this.name+"::"+i);

}
}
});
ScheduledExecutorService timer=Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(new Runnable(){

@Override
public void run() {
// TODO Auto-generated method stub
if(vechicles.size()>0){
boolean lighted=Lamp.valueOf(Road.this.name).isLighted();
if(lighted){
System.out.println(vechicles.remove(0)+" is passed!");
}
}
}

},
1,
1,
TimeUnit.SECONDS);

}
}


在这个类中,再一次学习了java.util.concurrent.Executors工具类,这个类是从1.5才开始有的,具有方法创建同步的单线程,或调度线程。以及内部类中引用外部类的成员变量 Road.this.name.

2,Lamp

Lamp是一个枚举类。因为总共有12条路线,这是确定的,当由南向北的限时用完后再开始走由南向西,接着走由东向西,再由东向南,在循环到开头由南向西。用枚举类可以很好的把路线连接起来,又不会在编程中产生意外的路线。

package com.traffic;

public enum Lamp {

S2N("N2S","S2W",false),S2W("W2S","E2W",false),E2W("W2E","E2S",false),E2S("S2W","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 next;
private String oppo;
private boolean lighted;

private Lamp(String oppo,String next,boolean lighted){
this.oppo=oppo;
this.next=next;
this.lighted=lighted;
}

public boolean isLighted(){
return lighted;
}
public void light(){
lighted=true;
System.out.println(name()+" is green");
Lamp.valueOf(oppo).lighted=true;

//		if(oppo!=null){
//			Lamp.valueOf(oppo).light();
//		}
}
public Lamp blackOut(){
lighted=false;
Lamp.valueOf(oppo).lighted=false;
System.out.println(name()+" is blackOut and light "+next);
Lamp nextLamp=Lamp.valueOf(next);
nextLamp.light();
return nextLamp;
}
}


这里又熟悉了枚举类,枚举类使每个独立的类的对象之间产生了联系。

3,灯控制器

灯控制器的代码很少,主要是调用Executors.newScheduledThreadPool()来定时循环切换红绿灯。

package com.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(){
currentLamp=currentLamp.blackOut();
}
},
10,
10,
TimeUnit.SECONDS);
}
}


4,测试类
package com.traffic;

public class MainClass {

public static void main(String[] args) {
// TODO Auto-generated method stub

String[] directions="S2N,S2W,E2W,E2S,N2S,N2E,W2E,W2N,S2E,E2N,N2W,W2S".split(",");
for(int i=0;i<directions.length;i++){
new Road(directions[i]);
}
new LampController();
}
}
上面类尤其要注意定义方向时不能写反了,否者出现的错误都不能找到。

通过这个项目,首先学习了如何去面对它,当看到一份需求文档,首先要读通文档,明白关键,把最核心的内容提取出来,像本项目,只需要考虑4条线路就可以,然后保证其他对应的4条线路同步。再就是剩下的4条右拐线路,只需要在定义时加入null,使其和其他线路在构造器中是相同的,再就是使用了java.util.concurrent包。提供了计时器,省去了自己使用实现Runnable接口,自己实现synchronized来创建线程,这些容易出错的代码。

还有就是,把12条线路的”车“装到ArrayList中,这是一个很好的方法,因为可以直接通过操作下标来移除最前面的“车”,然后自动实现后面的车占据前面的位置。

-----Java培训、Android培训、iOS培训、.Net培训、期待与您交流!-----
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: