------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
交通灯:每个方向的车都有三种行进路线
直行:优先通行
向右转:不受红绿灯限制,可以理解为灯常绿
向左转
模拟交通灯需要先模拟路况,每条路上要随机增加新的车辆,绿灯时亮绿灯的线路上要间隔时间减少一辆车
交通灯方面,四个右转的灯,其他八个灯两两成对,即只需对四个灯进行交替执行定时就行
首先先模拟路,有十二个方向的交通灯,所以也需要十二条路线,但只需用一个类实例化就行。
Road
public class Road {
private List<String> vechicles = new ArrayList<String>();
private String name = null;
public Road(String name){
this.name = name;
//创建线程池,线程池中的线程数为1,如果大于一,不会并发执行,前一个执行完后后一个才能执行
ExecutorService pool = Executors. newSingleThreadExecutor();
//匿名内部类
pool.execute( new Runnable(){
public void run(){
for(int i=1;i<1000;i++){
try {
//随机休息1-10秒,模拟车辆流通状况,1-10秒随机增加一辆车
Thread. sleep((new Random().nextInt(10)+1)*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//在集合中加入路以及车辆编号,作为路的车辆增减的依据,
//内部类引用外部类的成员,外部类.this.name
vechicles.add(Road.this.name+"-"+i);
}
}
});
//ScheduledExecutorService是一个接口,ScheduledThreadPoolExecutor是实现它的类
//该线程池可以执行定时任务,池中保存的线程数是1
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
//scheduleAtFixedRate是ScheduledExecutorService接口中的一个方法,创建并执行一个
//在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期,第一个参数通过匿名内部类
//的方式指定要定期操作的命令,延时第二个参数指定时间后开始执行,第三个参数是执行后的执行
//周期,第四个参数指定的是前两个时间的时间单位。该计时器绿灯时每隔一段时间就会从数组以队列
//的方式移除一个元素,相当于车辆经过。
timer.scheduleAtFixedRate(
new Runnable(){
public void run(){
if(vechicles.size()>0)
boolean lighted = Lamp.valueOf(Road.this .name).isLighted();
if(lighted){
System.out.println(vechicles.remove(0)+ " is traversing!");
}
}
},
1,
1,
TimeUnit.SECONDS);
}
}
Lamp用的是枚举来实现的,12个方向的road对应12个方向的交通灯,4个方向的右转恒绿,其余8个两两对应
只需要对4个方向的灯进行定时操作,不考虑黄灯的情况下,lighted只有两种状态即红和绿或false和true
public enum Lamp{
S2N("N2S","S2W",false),S2W("N2E","E2W",false) ,E2W("W2E","E2S",false),E2S("S2E","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 Lamp(String opposite,String next, boolean lighted){
this.opposite = opposite ;
this.next = next;
this.lighted = lighted;
}
private Lamp(){
}
private boolean lighted ;
private String opposite ;
private String next ;
public boolean isLighted(){
return lighted ;
}
//把灯变亮,同时把对面的灯也变亮
public void light(){
this.lighted = true;
if(opposite != null){
Lamp. valueOf(opposite).light();
}
}
//把灯变黑,并且将下一灯变绿(亮),返回下一个灯
public void blackOut(){
this.lighted = false;
if(oppsite!=null){
Lamp.valueOf(Oppsite).blackOut();
}
Lamp nextLamp = null;
if(next != null){
nextLamp = Lamp.valueOf(next);
nextLamp.light();
}
return nextLamp;
}
}
LampControl控制器控制当前正处于点亮的灯
public class LampController {
private Lamp currentLamp ;
public LampController(){
//点亮四路中的一路灯
currentLamp = Lamp.S2N ;
currentLamp.light();
//使用定时器每隔10秒将当前灯的状态改变,返回下一个点亮的灯为当前亮着的灯
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
new Runnable(){
public void run(){
currentLamp = currentLamp.blackOut();
}
},
10,
10,
TimeUnit.SECONDS);
}
}
总结: 将复杂的问题中的共性进行提取来获取真正需要操作的变量。
将不同的事物封装成对象,内部提供操作自己的方法。
工程中调度其他模块的控制单元需要单独封装成类。