------- android培训、java培训、期待与您交流! ----------
交通灯管理系统
· Concurrent [kən'kʌr(ə)nt]adj. 并发的;一致的;同时发生的
· Executors[ɪg'zɛkjətɚ]n. 执行者;[法] 遗嘱执行人;执行器
· scheduled['ʃedjuːld]adj. 预定的;调度
· service ['sɜːvɪs]n. 服务,服侍;服役;仪式
· pool [puːl]池
fixedrate固定频率
vechicles交通工具
directions [dɪ'rekʃ(ə)nz]n. 方向
Traversing n. 穿越,通过
opposite ['ɒpəzɪt; -sɪt] 对面
2.必须理解类和接口与方法
java.util.concurrent Executor接口:执行已提交的 Runnable 任务的对象。此接口提供一种将任务提交与每个任务将如何运行的机制(包括线程使用的细节、调度等)分离开来的方法。通常使用 Executor 而不是显式地创建线程。
void |
java.util.concurrent ScheduledExecutorService接口:
scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit) |
java.util.concurrent Executors类:此包中所定义的 Executor、ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 类的工厂和实用方法。
static ScheduledExecutorService | newScheduledThreadPool(int corePoolSize) |
一、题目要求
模拟实现十字路口的交通灯管理系统逻辑,具体需求如:
1、异步随机生成按照各个路线行驶的车辆。
例如:
由南向而来去往北向的车辆 ----直行车辆
由西向而来去往南向的车辆 ----右转车辆
由东向而来去往南向的车辆 ----左转车辆
。。。
2、信号灯忽略黄灯,只考虑红灯和绿灯。
3、应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。
4、具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。
5、注:
1)南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。
2)每辆车通过路口时间为1秒(提示:可通过线程Sleep的方式模拟)。
3)随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置。
4)不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。
二.题目图解:
1.对图形和题目分析
1) 汽车行驶路线共12条,每条路线作为一个对象存在。为了统一模型,
2) 假设每条路线有红绿灯存在。其中右转弯的4条路线的控制灯可以假设称为常绿状态。
3) 另外,其他的8条线路是两两成对的,可以归为4组。(原因:两个相对的灯一个变红,其相对的就要变绿)
4)所以,程序只需考虑图中标注了数字的4条路线的控制灯的切换顺序,这4条路线相反方向的路线的控制灯跟随这4条路线切换,不必额外考虑。
2.面向对象的分析。
面向对象有:红绿灯,红绿灯的控制系统,汽车,路线。
面向对象的经验:谁拥有数据,谁就对外提供操作这些数据的方法。
注意问题:
1)因为只有12个灯所以可以用枚举。
2)汽车与路线是绑定的。
3)汽车过红绿灯时不但要与交通灯有关系,还与汽车相互之间有关系。(原因是我们过红绿灯的时候不单只是看灯,还要看车。)
4)程序中如何知道自己前面是否有车,这时候则访问路线对象。(路就要有增加车辆和减少车辆的方法)
3.面向对象的设计。
路的设计:
1)因为有路才有车所以汽车与路线是绑定的,这样汽车可以当做是路的内部类。
2)因为每个车也是一个对象,所以创建一个集合来存储汽车对象。
3)制作定时器,每隔一秒检查对应的灯是否为绿,是则放行一辆车
4)汽车的通过路口则用,删除集合元素来来表示。
红绿灯的设计:
1)假设有12个灯所以就有12个对象,因为对象可以计算的出来所以用枚举表示。
2)不存在逻辑的灯:
车向右拐的四个交通灯:都是常绿的。(S2E,E2N,N2W,W2S)
3)存在逻辑的只有四组灯。
车直走的四个交通灯:一边灯变绿的时候,其相对的另一边也变绿,其为一组共两组。(S2N与N2S,E2W与W2E)
车左拐的四个交通灯:也是相对的,一边变绿,另外一边也变绿,所以也是两组。(S2W与N2E,E2S与W2N)
4)灯有三个变量:
一个是自己的状态。
一个是其相对方的灯。
一个是其下一个方向的灯。
5)灯的设计技巧:
一个灯变绿,那么其返回的值则表示下一个灯变红。
红绿灯控制系统设计:
1)初始化第一个交通灯
2)通过定时器,设定每隔10秒交通灯变一次颜色。
三.程序编写
1.Road类的编写
1)创建一个可以存储汽车的集合。
2)创建一个线程来创建汽车对象。
3)创建一个定时器,来检查汽车锁对应的等是否变绿。
package jiaotongdeng;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
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> vechicles = new ArrayList<String>();
//每条路要有名字,这样才好为车起名字。
private String name = null;
public Road(String name){
this.name = name;
//模拟车辆不断随机上路的过程,使用线程池,通过产生单个线程的方法,创建一个线程池 .
ExecutorService pool = Executors.newSingleThreadExecutor();//Executors为线程池中单线程
pool.execute(new Runnable() {
public void run() {
//用构造方法产生999量车
for(int i =1; i < 1000; i++){
try {
Thread.sleep((new Random().nextInt(10) + 1) * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//车辆进入路线中
//内部类访问外部成员Road.this
vechicles.add(Road.this.name + "_" + 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){//当灯是绿的。lighted表示绿灯。
System.out.println(vechicles.remove(0) + " is traversing!");
}
}
}
},
1, //指过多少秒去干这个事
1, //再过多少秒接着干
TimeUnit.SECONDS);//时间的度量单位
}
}
2.Lamp类的编写
1)因为只有12个交通灯,所以直接用枚举来创建对象更方便。
2)为灯的枚举设置属性,分别指目前的灯的对面的灯,下一个灯,等是否是绿色。
3)创建三个变量,一个是自己的状态,一个表示相对的灯,一个表示下一个灯。
4)创建检查灯是否变绿的方法。
5)创建让其对应的灯同时变绿的方法。
6)创建把等变红的方法,并且返回下一个灯。
package jiaotongdeng;
public enum lamp {
//S代表南,N代表北,W代表西,E代表东。
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 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();
}
System.out.println(name() + "lamp is Green,下面总共应该有6个方向能看到汽车穿过!");
}
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;
}
}
3.LampControlle类的编写
1)初始化交通灯。
2)设置定时器让灯每隔10秒变一次颜色。
package jiaotongdeng;
import java.util.concurrent.Executor;
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();//指定第一个灯为绿
//定时器,没隔10秒钟让这个灯变黑下一个等变绿。
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
new Runnable(){
public void run() {
System.out.println("来了");
//每隔10秒钟把当前的灯变黑
currentLamp = currentLamp.blackOut();
}
},
10,
10,
TimeUnit.SECONDS);
}
}
4.mainClass主函数的编写
1)创建存储路方向的数组。
2)创建路方位的对象。
3)创建交通控制系统。
package jiaotongdeng;
public class MainClass {
/**
* @param args
*/
public static void main(String[] args) {
//创建存储方位的数组。
String [] directions = new String[]{
"S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2S"
};
//创建路方位的对象。
for(int i = 0; i < directions.length; i++){
new Road(directions[i]);
}
//创建交通控制系统
new lampController();
}
}