Java高新技术之交通灯管理系统(java枚举,java线程池)

来源:互联网 发布:哪款理财软件好 编辑:程序博客网 时间:2024/06/16 01:48

先看图,让我们先理清楚现实生活中十字路口的交通灯是怎么运行的:

我们如果认真观察会发现,十字路口有12条路线。十字路口每条方向上的路线的右转车辆是不考虑红绿灯的(即图中4条黑色路线,除了一些人多的特殊地段会设置)

1.首先假设你一到十字路口就看到,南北方向的直行车辆在行驶(图中两条绿色路线),其它三大路线(2条蓝色、2条红色和2条紫色)都在等待。

2.南北方向走完后,就轮到南北方向的左转路线(即蓝色路线),注意不是红色也不是紫色。(这时另外的三大路线在等待)

(注意:

a.南北、东西、南西、北东、东南、西北8条路线的车辆是同时交替放行的。解释:有南到北的,就有北到南的,例如图中,两条绿色的路线;有南到西,就有北到东,图中,两条蓝色路线等。

b.同方向等待车辆应该先放行直行车辆,再放行左转车辆。解释:例如南北方向的两条绿色路线在等待时(这时南北方向的左转车辆已经走完,蓝色路线),先放行东西方向的两条红色路线,等红色路线走完后,再放行东西方向的左转车辆,紫色路线

)

3.这时轮到东西方向的直行车辆行驶(即图中,两条红色路线),这时另外的三大路线在等待

4.最后轮到东西方向的左转车辆(即图中,两条紫色路线),这时另外的三大路线在等待。

5.重复步骤"1"

6.重复步骤"2"

7.不说了,你懂了........

交通灯管理系统的项目需求:

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

例如:

a.由南向北去的车辆....直行车辆(图中,绿色路线)

b由西向南去的车辆....右转车辆(图中,黑色路线,其实认真观察生活会发现,十 字 路口的每个右转弯的灯永远都是绿的或者没有设置)

c.由东向南去的车辆....左转车辆(图中,紫色路线)

..........................

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

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

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

5.每辆车通过路口的时间设置为1(提示:可通过线程的sleep方法模拟)

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

面向对象的分析与设计:

1.每条线路上都会出现多辆车,路线上要随机增加新的车,在灯变绿期间要每秒钟减少一辆车

设计一个Road类来表示路线,每个Road对象代表一条路线,总共12条,即系统中总共要产生12Road实例对象

每条路线上随机增加新的车辆,增加到一个集合中保存

每条路线每隔一秒都会检查控制本路线的灯是否为绿,是则将本路线保存的集合中的第一辆车移除,即表示车穿过路口

下面看Road代码(具体分析看代码注释):

public class Road {//定义一个集合用来存储每条路线上的车辆private List<String> vehicles=new ArrayList<String>();//路线的名字:例如S2N N2S E2W  W2W  ....private String name;public Road(String name){this.name=name;//随机的往list集合中增加车辆,即多少辆车开到哪条路线路上ExecutorService pool=Executors.newSingleThreadExecutor();pool.execute(new Runnable() {@Overridepublic void run() {for(int i=1;i<=1000;i++){try {//往集合中增加车辆不可能一下子就来了1000辆车吧,所以要每隔n秒增加一辆车(这个n是指1到10之间的随机数)Thread.sleep((new Random().nextInt(10)+1)*1000);} catch (InterruptedException e) {e.printStackTrace();}//哪条路线上的第几辆车vehicles.add(Road.this.name+"_"+i);}}});//定义一个线程池,它是支持周期性的任务执行。//这个线程池的作用是:你不可能车开到路上就不走了吧(堵车或车祸不考虑),所以要定期的让车行驶//即定期的让车穿过绿灯ScheduledExecutorService timer=Executors.newScheduledThreadPool(1);//参数:第一个,要执行的线程;第二个,每隔多长时间执行一次线程;第三个,执行的周期;第四个,指定第二个和第三个参数代表的数值,秒timer.scheduleAtFixedRate(new Runnable() {@Overridepublic void run() {//首先要判断路线上是否有车,没车你还搞什么!!if(vehicles.size()>0){//获取当前路线上的灯是否为绿,是绿就让这条路线上的车辆穿过boolean lightGreen=Lamp.valueOf(Road.this.name).getLighted();if(lightGreen){System.out.println(vehicles.remove(0)+".......穿过绿灯");}}}}, 10, 10, TimeUnit.SECONDS);}}

2.每条路线每隔一秒都会检查控制本路线的灯是否为绿,一个灯有绿变红时,应该将下一个方向的灯变绿(关于枚举可以看我才这篇博客

点击打开链接

设计一个Lamp类来表示一个交通灯,每个交通灯都维护一个状态,绿或者红,每个交通灯要有变亮和变黑的方法,并且能返回自己的红绿状态

总共有12条路线,所以,系统中总共要产生12个交通灯。右转弯的路线本来不受等控制,但是为了让程序采用同意思的处理方式,

故假设出有四个右转弯的灯,只是这些灯为常绿,即永远不变红。除了右转弯方向的其他8条路线的灯,它们是两两成对的,可以归为4组,

所以,在编程处理时,只要从这4组中各取出一个灯,对这4个灯依次循环变绿,与这4个灯方向对应的灯则随之一同变化,

因此Lamp类中要有一个变量来记住自己相反方向的灯,在一个Lamp对象的变绿和变红方法中,将对应方向的灯也变绿和变红。

每个灯变红时,都伴随着下一个等的变红,Lamp类中还用一个变量来记住自己的下一个灯。

下面看Lamp代码(具体看注释):

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),E2N(null,null,true),N2W(null,null,true),W2S(null,null,true);//定义一个变量,记录每条路线上的每个方向上的灯的状态,true为绿,false为红private boolean lighted;//每条路线对应的等。例如:S2N对应的灯是N2Sprivate String oppositeLight;//每条路线对应的下一条路线的灯,例如:S2N路线对应的下一条路线S2W对应的灯private String nextLight;private Lamp(String oppositeLight,String nextLight,boolean lighted){this.oppositeLight=oppositeLight;this.nextLight=nextLight;this.lighted=lighted;}public boolean getLighted(){return lighted;}//将灯设置为绿public void setGreen(){this.lighted=true;//判断是否有对应的灯if(oppositeLight!=null){Lamp.valueOf(oppositeLight).setGreen();}System.out.println(name()+" lamp is green, 您将看到有6个方向的车可以行使");}//将灯设置为红,并且将下一条路线的灯设置为绿public Lamp setRed(){this.lighted=false;//判断是否有对应的灯if(oppositeLight!=null){Lamp.valueOf(oppositeLight).setRed();}//将下一个灯变为绿色,并且返回出去Lamp nextLlight=null;if(nextLight!=null){nextLlight=Lamp.valueOf(nextLight);System.out.println("绿灯从"+name()+" --------切换为------->"+nextLight);nextLlight.setGreen();}return nextLlight;}}

3.要让每条路线上的红绿灯的系统运行起来,还需要另外一个控制整个交通系统的类,LampController

控制每条线路上红绿灯的状态,每隔10秒钟变化一次。

下面看LampController代码(具体看注释)

public class LampController {//临时变量,记住当前路线车的状态,以及设置红绿灯的状态private Lamp currentLamp;public LampController(){//总得有个开始的路线吧,所以这里设置南到北路线的开始执行,currentLamp=Lamp.S2N;//将南到北路线上的灯设置为绿色,并且setGreen方法内部会将S2N的对应路线即N2S的灯也设置为绿色currentLamp.setGreen();ScheduledExecutorService timer=Executors.newScheduledThreadPool(1);timer.scheduleAtFixedRate(new Runnable(){public void run(){//10秒钟以后将这条路线上的灯设置为红色,并且将对应路线上的灯也设置为红色,//并且将下一条路线上的灯设置为绿色,并返回一个Lamp枚举的对象,                                                //这样整个交通灯的系统就跑起来了currentLamp=currentLamp.setRed();}}, 10,10, TimeUnit.SECONDS);}}

4.下个测试类:MainTest(具体看代码注释)

public class MainTest {public static void main(String[] args) {/* 第一步:让每个方向上都有车 1.这里是利用线程的方式让每个方向上都有机会增加车辆,因为有12条路线,这里采用for循环的方式 创建每条路线上的车,当一new Road(directions[i]);时就会倒Road类中的构造函数中, 构造函数有两个线程池,一个是增加车辆,另一个是让车穿过绿灯, 2.但是这时会阻塞在"boolean lightGreen=Lamp.valueOf(Road.this.name).getLighted();"这!!! 为什么? 因为它要判断当前方向上的灯是否是绿色的,可是整个交通灯系统没有跑起来啊,所以这里的线程会阻塞,看第二步: * *///将12条路线都加到Road中的线程池中,让每条路线上都有车,再说String[] directions=new String[]{"S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N","S2E","E2N","N2W","W2S"};//这里是利用for循环创建12个线程,一个一个创建太麻烦了,所以用for循环for(int i=0;i<directions.length;i++){new Road(directions[i]);}/*第二步 让整个交通系统运行起来吧! 控制每条路线上的红绿灯,其实这里只是控制了"S2N","S2W","E2W","E2S"这四条路线, 它们各自对应的路线的灯都是交替运行的,而每条路线的右转弯是不考虑的 1.当一new LampController();时会到LampController类中的构造函数中, 构造函数同样有个线程池,在线程池运行前有个"currentLamp.setGreen();"这时整个交通系统就已经跑起来了 2.当执行到线程池那块代码时,它会每隔10秒将当前路线上的灯设置为红色(即currentLamp=currentLamp.setRed();), 灯设置为红色后,该函数会返回一个Lamp对象,这就是下一个路线上的灯了 3.第一步中的线程再跑,第二步这里的线程也在跑,所以整个系统就OK了!!! * */new LampController();}}
5.关于线程池可以查看这篇博客点击打开链接

总结:

       这个交通灯系统是想了好久才明白的啊!想做好这个交通灯,你得对现实生活中十字路口的交通有所了解。然后就是把握住”一切皆对象”的道理来做就行啦!12条路线!!!你把它看做一个对象;各个方向上的灯你把它看做对象;还有最后一个LampController这个类。

       做了这个项目之后感觉以前学的很零散的东西都整合到一起了,也知道学的那些知识点怎么用了。例如:枚举,在这个项目中可不是简单的定义一个枚举啊,中间用到了枚举中的构造方法,属性和普通方法,如果你可以把这个项目吃透,那么枚举就不成问题了!再例如,java1.5的新特性线程池等。在这个项目中都很好的运用到了!!!

0 0
原创粉丝点击