黑马程序员技术交流社区

标题: 一种不同张孝祥老师视频中交通灯管理系统的实现 [打印本页]

作者: mytongyong    时间: 2014-7-21 13:04
标题: 一种不同张孝祥老师视频中交通灯管理系统的实现

个人设计的另外一种关于张老师的交通灯管理系统的实现方法,前期的分析和张老师的没什么区别,就是在具体代码实现时候用的是我自己的代码,和张老师的代码还是有一点区别的,但在结果应该是没有区别吧,我也没有认真的测试,唯一的感触就是找bug花的时间是数倍于写代码的时间。呵呵,源码就粘在下面了。考虑字数限制,源码我没有全粘。
先说一下我的思路吧,在前期路径分析上和张老师的分析是一样的,但是就是再用面向对象的思想抽象出类的时候我和张老师的有一些不一样。
我抽象出了如下几个类:
Lamp: 很简单,就是封装了交通灯的颜色RED和GREEN两个枚举对象。
Lampinfo:用来描述交通灯的这个对象,我想就是一个交通灯的这个类,在一个十字路口只能有一个,不能同时产生多个,所以我把这个类设计成了单例,同时它也应该有交通灯变换的时间(time)这个变量,也应该有两条由南到北(Route.N2S),由西到东(Route.W2E)的两条路(这样才能组成十字路口么),要设置时间,所以一定要有time的set和get方法。这个类,对外要展示的就是从南到北和从北到南这两条路的红绿灯的信息,所以我定义了一个图(lampinfo)的结构来把路径与灯棒定在一起。并对外值提供了get方法。
Lampinfo.java
  1. public class Lampinfo {               

  2.         //方向从北向南,从西向东
  3.         Route[] route = {Route.N2S,Route.W2E};
  4.         //数据结构怎么定义,代表不同的路况默认是北南方向绿,西东方向红
  5.         private Map<Route, Lamp> lampinfo = new HashMap<Route, Lamp>();
复制代码
Rote:这个类是一个枚举类,就是实现了12个方向的枚举对象,和Lamp类是一个性质的,相信大家都懂的,只不过我重写了tostring方法,让输出的信息更好看一些。
  1. package cn.itcast.mytraffic;

  2. public enum Route {
  3.         //定义12个方向
  4.         //右转,四个方向,不需要看红绿灯
  5.         N2W,E2N,W2S,S2E,
  6.         //左转,直行需要看红绿灯
  7.         //当N-S和S-N方向通畅时
  8.         //N-S方向直行,左转,S-N方向直行,左转
  9.         N2S,N2E,S2N,S2W,
  10.         /*
  11.          * 当W-E方向和E-W方向通畅时
  12.          * W-E方向直行,左转,E-W方向直行,左转
  13.          */
  14.         W2E,W2N,E2W,E2S;
  15.         //以上共12中行驶路线
  16.         //重新实现tostring方法,用来输出实际的路线信息
  17.         public String toString() {
  18.                 switch (this) {
  19.                 case N2W:                       
  20.                         return "北向西,右转";
  21.                 case E2N:
  22.                         return "东向北,右转";
  23.                        
  24.                 case W2S:               
  25.                         return "西向南,右转";
  26.                        
  27.                 case S2E:
  28.                         return "南向东,右转";
  29.                        
  30.                 case N2S:
  31.                         return "北向南,直行";
  32.                        
  33.                 case N2E:
  34.                         return "北向东,左转";
  35.                        
  36.                 case S2N:
  37.                         return "南向北,直行";
  38.                        
  39.                 case S2W:
  40.                         return "南向西,左转";               
  41.                 case W2E:
  42.                         return "西到东,直行";
  43.                 case W2N:
  44.                         return "西到北,左转";
  45.                 case E2W:
  46.                         return "东到西,直行";
  47.                 case E2S:
  48.                         return "东到南,左转";
  49.                 default:
  50.                         System.out.println("出错啦!!");
  51.                         break;
  52.                 }
  53.                 return null;
  54.         };
  55. }
复制代码

Road:这个我和张老师的想法一样,或者说是在他的引导下,但在实现上我和张老师的有区别,Road这个类是要产生增加车和减少车的方法的,而且这个方法是动态,十字路口,十二个方向,在路上跑的每台车都要有自己的方向,所以我认为生成的车要有自己的方向。同时我用队列来实现车的增加和减少,也就避免了撞车的可能吧,因为队列不是有尾端插入,前段删除的性质嘛。
Road.java
  1. package cn.itcast.mytraffic;


  2. import java.util.LinkedList;
  3. import java.util.Queue;
  4. import java.util.Random;
  5. import java.util.concurrent.Executors;
  6. import java.util.concurrent.TimeUnit;

  7. public class Road {
  8.        
  9.         //N-S和S-N是绿灯的行驶车辆信息这里考虑用队列来实现,其好处是不用判断前面的车是否出去了,因为队列就是前端删除,后端插入。
  10.         //private List<Route> CarN2S = new ArrayList<Route>();
  11.         private Queue<Route> CarN2S = new LinkedList<>();
  12.         //W-E和E-W是绿灯的形式车辆信息
  13.         //private List<Route> CarW2E = new ArrayList<Route>();
  14.         private Queue<Route> CarW2E = new LinkedList<>();
  15.         //封装从N-S和S-N是绿灯时车辆所有可能的行驶方向
  16.         private Route[] routeN2S ={Route.N2S,Route.N2E,Route.S2N,Route.S2W,Route.N2W,Route.S2E,Route.W2S,Route.E2N};
  17.         //封装从W-E和E-W是绿等是车辆所有可能的形式方向
  18.         private Route[] routeW2E = {Route.W2E,Route.W2N,Route.E2N,Route.E2S,Route.E2W,Route.W2S,Route.S2E,Route.N2W};
  19.         //用队列的方式实现车的添加和减少
  20.         public Road(){
  21.                 //从N-S方向先随机生成5辆车               
  22.                 for(int i=0;i<5;i++){               
  23.                         CarN2S.offer(routeN2S[new Random().nextInt(7)]);
  24.                 }
  25.                 //从W-E方向也随机生成5辆车
  26.                 for(int i=0;i<5;i++){
  27.                         CarW2E.offer(routeW2E[new Random().nextInt(7)]);
  28.                 }
  29.         }
  30.         private  void addCar(){
  31.                 //每1秒路上增加1辆车
  32.                
  33.                 if(!CarN2S.offer(routeN2S[new Random().nextInt(7)])){
  34.                         System.out.println("车辆增加异常!");
  35.                 }
  36.                
  37.                 //每1秒路上增加一辆车
  38.             if(!CarW2E.offer(routeW2E[new Random().nextInt(7)])){
  39.                     System.out.println("车辆增加异常!");
  40.             }
  41.             //System.out.println("进入addCar了");
  42.         }
  43.         public void Start(){
  44.                 //创建一个可以调度线程池用来分别添加两个方向的车
  45.                  Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
  46.                                 new Runnable() {                                       
  47.                                         @Override
  48.                                         public void run() {
  49.                                                 // TODO Auto-generated method stub
  50.                                                 //这么做线程应该发生了死锁?不是死锁,无法插入元素了,数组越界了,小bug找了好久。
  51.                                                 addCar();
  52.                                         //        System.out.println("从addCar出来了");
  53.                                         }
  54.                                 },
  55.                                 1,
  56.                                 2,
  57.                                 TimeUnit.SECONDS);
  58.         }
  59.         public Route getCarN2S() {       
  60.                 return CarN2S.poll();
  61.         }
  62.         public Route getCarW2E() {
  63.                 return CarW2E.poll();
  64.         }
  65.        
  66. }
复制代码
TrafficControl:这个类是核心,其他的类都是为它服务的,因为这个系统的调度在这里。这里我就实现了一个schedule方法,根据Lampinfo类的lampinfo.getLampinfo()方法来获取当前路口的颜色,如果为绿色,则调度车辆运行。
TrafficControl.java
  1. package cn.itcast.mytraffic;

  2. import java.util.Map;
  3. import java.util.concurrent.Executors;
  4. import java.util.concurrent.TimeUnit;

  5. public class TrafficControl {
  6.        
  7.         /*private Lamp[] lamps={Lamp.RED,Lamp.GREEN};*/
  8.         private Road road;
  9.         private Lampinfo lampinfo;
  10.        
  11.         public TrafficControl(Road road,Lampinfo lampinfo){
  12.                 this.road = road;
  13.                 this.lampinfo = lampinfo;
  14.         }
  15.         //根据灯的信息来调度不同路线上的车辆
  16.         public synchronized void schedule(){
  17.                 //判断当前的红绿灯颜色
  18.                 Map<Route, Lamp> lamp =  lampinfo.getLampinfo();
  19.                 //从南向北行驶的所有车辆应该获得该方向的灯的颜色
  20.                 //绿灯,可以行驶
  21.                 if(lamp.get(Route.N2S) == Lamp.GREEN){
  22.                         //线程在这里面等待获得队列删除后返回的元素,程序在这里面发生了死锁?
  23.                         Route carinfN2S= road.getCarN2S();
  24.                         if(carinfN2S == null){
  25.                                 System.out.println("没车了!!");
  26.                         }else {
  27.                                 System.out.println("从南向北方向畅通"+carinfN2S.toString() + "正在行驶");
  28.                         }
  29.                        
  30.                 }else if (lamp.get(Route.W2E) == Lamp.GREEN) {
  31.                         //线程在这里面等待获得队列删除后返回的元素,程序在这里面发生了死锁?
  32.                        
  33.                         Route carinfW2E = road.getCarW2E();
  34.                         if(carinfW2E == null){
  35.                                 System.out.println("没车了!!");
  36.                         }else{
  37.                                 System.out.println("从西向东方向畅通" + carinfW2E.toString() + "正在行驶");
  38.                         }
  39.                        
  40.                 }               
  41.         }
  42.         public void Start(){
  43.                 Executors.newScheduledThreadPool(1).scheduleAtFixedRate(
  44.                                 new Runnable() {
  45.                                         @Override
  46.                                         public void run() {
  47.                                                 schedule();
  48.                                         }
  49.                                 },
  50.                                 2,
  51.                                 1,
  52.                                 TimeUnit.SECONDS);
  53.         }
  54.        
  55. }
复制代码
StartMain类是一个启动类,无需多解释了。
  1. package cn.itcast.mytraffic;

  2. public class StartMain {
  3.         public static void main(String[] args) {
  4.                 Road road = new Road();
  5.                 Lampinfo lampinfo = Lampinfo.newinstance();
  6.                 TrafficControl trafficControl = new TrafficControl(road, lampinfo);
  7.                 //开启交通灯
  8.                 lampinfo.Start();
  9.                 //路上开始不断的增加车辆
  10.                 road.Start();
  11.                 //开始调度
  12.                 trafficControl.Start();
  13.         }
  14. }
复制代码
以上就是全部的实现方式,作为学习张老师的全部高新视频的一个总结吧,不多说了,博客还没写完呢,没时间测试了,我不保证程序会完美运行,反正我捂脸贡献出代码了,大家轻拍..........
附件是源代码。







Traffic.zip

16.12 KB, 下载次数: 129


作者: 长跑※终点    时间: 2014-7-21 13:08
厉害,高手
作者: 长跑※终点    时间: 2014-7-21 14:24
:Q忍不住又来赞下楼主




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2