/* 交通灯管理系统: 中间涉及到的对象: 路,汽车,灯,灯控制器 路线:共12条,4条主线(它们有与对之对应的路线),4条右拐的路线(灯为长绿) 面向对象:每一个对象它们都有具体的任务 核心技巧:我们把数据给设置成私有的,然后谁拥有数据,谁就对外提供操作这些数据的方法 由于汽车我们在这里并不是看到汽车在路上跑,而我们想捕捉到汽车经过路口的瞬间 所以我们这里汽车使用字符串即可。 ------------------------------------------------------------------------------ 路线类的书写: 因为路上是有很多车,而车要经过路口的时候,它不是看到对应方向的灯变绿了,就直接冲过 路口了,而是它要问一下它前面有没有其它的车,这个要问谁了?问路就可以了。 路上有很多车,所以路上就应该有一个存放这些车辆的集合。而添加车减少车,其实就是在对 路上的集合进行操作。所以路线这个类就应该提供增加与减少车辆的方法 车辆:vehicle 使用并发库的线程池随机往当前路线上添加车辆 使用并发库的定时调度每隔一秒将集合中的第一辆车给移除。 有两个前提,第一个是集合中有车,第二个是当前路线上的灯是绿的状态 ------------------------------------------------------------------------------ 灯类的书写: 因为总共12组灯,我们只用写4组,其它还有4组是与之对应的灯。另外4组是右拐的灯,它们是 长绿的。 我们使用枚举来进行操作 S2N,S2W,E2W,E2S, N2S,N2E,W2E,W2N, S2E,E2N,N2W,W2S; 每个灯有自己的状态 每个灯它有一个方法是可以返回自己的状态的 当前路上的灯变绿的时候要把与之对应的灯给变绿 当前路上的灯变红的时候要把与之对应的灯变红,并且还要把下一组灯给变绿 我们的当前的灯,下一组灯,和当前灯的状态都是通过构造方法进行赋值的。 需要注意的是,我们这里不存储对象,而是存储灯的名称,因为我们在传递参数的时候,会出现有的变 量我们还没有定义出来,而我们就已经在使用了。程序会报错,所以我们就选择使用了字符串进行存储 灯的名称 ------------------------------------------------------------------------------ 灯控制器的书写 在灯控制器创建的时候有一个默认的灯而且这个灯是绿的 这个当前的灯我们在构造方法里面进行赋值的 灯控制器要每隔10秒改变一下灯的状态 我们使用定时调度来完成 改变灯的状态就是让当前的灯给变红 但是当前的灯变红了、要记录住下一组变绿的灯 我们该如何知道了? 我们让当前的灯变红的方法中返回下一组变绿的灯 在当前的灯变红的时候,使用当前的这个变量记录住下一组变绿的灯 ------------------------------------------------------------------------------ 主类的书写: 创建12条线程的集合 为了程序的简洁和方便我们使用String数组来操作 然后遍历集合,创建路线对象 然后创建灯控制器对象 为了便于测试,我们还需要在程序中打印一些信息,以便于我们观察测试的结果。只是为 了方便于我们的调试 */ public class Road { //每个路线上都有自己的车辆。因为有很多所以使用集合进行存储 private List vehicles=new ArrayList(); private String name; //记录住传递进来的路线名,方便于以后使用 //每条路线都应该有自己的名字 //在路线创建的时候就要给路线指定名称 //通过构造方法来实现 public Road(String name){ this.name=name; //使用jdk 1.5的类库另起一条线程来添加车辆到集合中 //我们使用的是并发库 //创建了一个只有一个线程的线程池 ExecutorService pool=Executors.newSingleThreadExecutor(); //线程所要执行的任务 pool.execute(new Runnable() { @Override public void run() { //往路线中添加车辆 for(int i=1;i<1000;i++){ try { Thread.sleep((new Random().nextInt(10)+1)*1000); //让线程在1-10毫秒随机休眠 } catch (InterruptedException e) { e.printStackTrace(); } //想让线程休眠 //不能直接在构造方法里面休眠。因为对象还没有创建出来。我们需要 //另起一条线程,让它执行添加的操作。即是在对象创建出来的时候, //另起一条线程慢些添加车辆到集合中 //我们使用jdk 1.5的那套类库来操作,即线程池 vehicles.add(Road.this.name+"_"+i); //一次添加很多车辆到路线中,路线上会出现塞车的 //我们想让添加的时候慢些添加 } } }); //因为要每隔1秒,当前线上就有一辆车经过路口,只是在当前路线的灯为绿的情况下 //所以我们作用定时器的定时调度来完成 ScheduledExecutorService timers=Executors.newScheduledThreadPool(1); //调度线程池中也只是有一个线程 timers.scheduleAtFixedRate( new Runnable() { @Override public void run() { //移除集合中的车辆 //两个前提,集合中有车辆的时候 //并且是当前的路线上的灯是绿灯 if(vehicles.size()>0){ // boolean lighted=true; //当前路线上的灯的状态 //Lamp.valueOf可以根据名称返回枚举类中的实例 boolean lighted=Lamp.valueOf(Road.this.name).isLighted(); //通过路线的名称获取到当前路线上的 //灯的状态 //>0即说明是有数据 if(lighted){ //从集合中移除对象的时候,返回的是被移除的对象 System.out.println(vehicles.remove(0)+" is travering!...."); } } } } , 1, 1, TimeUnit.SECONDS); //重复执行调度 } } 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); //private Lamp(){} //定义一个无参的构造方法是为了不让上面的代码在未处理到它的时候不报错 private Lamp(String oppoSited,String next,boolean lighted){ //三个参数分别为:对应方向上的灯,下一组灯,灯的状态 this.oppoSited=oppoSited; this.next=next; this.lighted=lighted; } //每个灯有自己的状态 private boolean lighted; //定义变量记录对应方向的灯 private String oppoSited; //它是通过构造方法来进行赋值的 //下一组灯 private String next; //每个灯它有一个方法是可以返回自己的状态的 public boolean isLighted(){ return lighted; } //每个灯它是有变绿和变红的方法(Red:blackOut,Green:light) public void light(){ lighted=true; //当前的灯变绿要把与之对应的灯给变绿 if(oppoSited!=null){ Lamp.valueOf(oppoSited).light(); } System.out.println(name()+"is green,我们应该可以看到6个方向上的车经过路口"); } public Lamp blackOut(){ lighted=false; //当前的灯变红要把与之对应的灯给变红 if(oppoSited!=null){ Lamp.valueOf(oppoSited).blackOut(); // 把下一组灯给变红 } Lamp nextLamp=null; //当前的灯变红的时候要把下一组的灯给变绿 if(next!=null){ //在灯由红切换成绿的状态之前,打印出一条信息 System.out.println(name()+"---->>>>green"); nextLamp=Lamp.valueOf(next); //把下一组灯给变绿 nextLamp.light(); } return nextLamp; //返回下一组变绿的灯 } } public class LampController { //在灯控制器创建的时候有一个默认的灯而且这个灯是绿的 private Lamp currentLamp; //这个当前的灯我们在构造方法里面进行赋值的 public LampController(){ currentLamp=Lamp.S2N; currentLamp.light(); //灯控制器要每隔10秒改变一下灯的状态 //我们使用定时调度来完成 ScheduledExecutorService timers=Executors.newScheduledThreadPool(1); timers.scheduleAtFixedRate( new Runnable() { @Override public void run() { //改变灯的状态就是让当前的灯给变红 currentLamp=currentLamp.blackOut(); //但是当前的灯变红了、要记录住下一组变绿的灯 //我们该如何知道了? //我们让当前的灯变红的方法中返回下一组变绿的灯 //在当前的灯变红的时候,使用当前的这个变量记录住下一组变绿的灯 } } , 10, 10, TimeUnit.SECONDS); } } public class MainClass { public static void main(String[] args) { // 创建12条线程的集合 // 为了程序的简洁和方便我们使用String数组来操作 String[] directions = new String[] { "S2N", "S2W", "E2W", "E2S", "N2S","N2E", "W2E", "W2N", "S2E", "E2N", "N2W", "W2S" }; for(int i=0;i<directions.length;i++){ new Road(directions[i]); } //创建灯控制器 new LampController(); } }
《黑马程序员》交通灯管理系统项目回顾,布布扣,bubuko.com
原文:http://blog.csdn.net/zhizguoz/article/details/22141393