交通灯


问题分析:

类设计:

Road

  1. 每个 Road 对象都有一个 name 成员变量来代表方向,有一个 vehicles 成员变量来代表方向上的车辆集合。
  2.
Road 对象的构造方法中启动一个线程每隔一个随机的时间向 vehicles 集合中增加一辆车(用一个 路线名 _id” 形式的字符串进行表示)。
  3.
Road 对象的构造方法中启动一个定时器,每隔一秒检查该方向上的灯是否为绿,是则打印车辆集合和将集合中的第一辆车移除掉。

源码如下:

package com.isoftstone.interview.traffic;

 

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;

 

/**

 * 每个Road对象代表一条路线,总共有12条路线,即系统中总共要产生12个Road实例对象。

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

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

 * @author 张孝祥 www.it315.org

 *

 */

public class Road {

        private List vechicles = new ArrayList();

        

        private String name =null;

        public Road(String name){

               this.name = name;

               

               //模拟车辆不断随机上路的过程          

               ExecutorService pool = Executors.newSingleThreadExecutor();

               pool.execute(new Runnable(){

                       public void run(){

                               for(int i=1;i<1000;i++){

                                      try {

                                              Thread.sleep((new Random().nextInt(10) + 1) * 1000);

                                      } catch (InterruptedException e) {

                                              e.printStackTrace();

                                      }

                                      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){

                                                             System.out.println(vechicles.remove(0) + " is traversing !");

                                                     }

                                              }

                                              

                                      }

                               },

                               1,

                               1,

                               TimeUnit.SECONDS);

               

        }

}

(二) Lamp
  1.
系统中有 12 个方向上的灯,在程序的其他地方要根据灯的名称就可以获得对应的灯的实例对象,综合这些因素,将 Lamp 类用 java5 中的枚举形式定义更为简单。
  2.
每个 Lamp 对象中的亮黑状态用 lighted 变量表示,选用 S2N S2W E2W E2N 这四个方向上的 Lamp 对象依次轮询变亮, Lamp 对象中还要有一个 oppositeLampName 变量来表示它们相反方向的灯,再用一个 nextLampName 变量来表示此灯变亮后的下一个变亮的灯。这三个变量用构造方法的形式进行赋值,因为枚举元素必须在定义之后引用,所以无法再构造方法中彼此相互引用,所以,相反方向和下一个方向的灯用字符串形式表示。  
  3.
增加让 Lamp 变亮和变黑的方法: light blackOut ,对于 S2N S2W E2W E2N 这四个方向上的 Lamp 对象,这两个方法内部要让相反方向的灯随之变亮和变黑, blackOut 方法还要让下一个灯变亮。
  4.
除了 S2N S2W E2W E2N 这四个方向上的 Lamp 对象之外,其他方向上的 Lamp 对象的 nextLampName oppositeLampName 属性设置为 null 即可,并且 S2N S2W E2W E2N 这四个方向上的 Lamp 对象的 nextLampName oppositeLampName 属性必须设置为 null ,以便防止 light blackOut 进入死循环。
源码如下:

package com.isoftstone.interview.traffic;

 

/**

 * 每个Lamp元素代表一个方向上的灯,总共有12个方向,所有总共有12个Lamp元素。

 * 有如下一些方向上的灯,每两个形成一组,一组灯同时变绿或变红,所以,

 * 程序代码只需要控制每组灯中的一个灯即可:

 * s2n,n2s    

 * s2w,n2e

 * e2w,w2e

 * e2s,w2n

 * s2e,n2w

 * e2n,w2s

 * 上面最后两行的灯是虚拟的,由于从南向东和从西向北、以及它们的对应方向不受红绿灯的控制,

 * 所以,可以假想它们总是绿灯。

 * @author 张孝祥 www.it315.org

 *

 */

/**/

 

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(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个方向能看到汽车穿过!");

               

        }

        

        /**

         * 某个灯变红时,对应方向的灯也要变红,并且下一个方向的灯要变绿

         * @return 下一个要变绿的灯

         */     

        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;

        }

}
(三) LampController
  1.
整个系统中只能有一套交通灯控制系统,所以, LampController 类最好是设计成单例。
  2.LampController
构造方法中要设定第一个为绿的灯。  
  3.LampController
对象的 start 方法中将当前灯变绿,然后启动一个定时器,每隔 10 秒将当前灯变红和将下一个灯变绿。
源码如下:
package com.isoftstone.interview.traffic;

 

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("来啊");

                                              currentLamp = currentLamp.blackOut();

                               }

                               },

                               10,

                               10,

                               TimeUnit.SECONDS);

        }

}

MainClass
  1.
for 循环创建出代表 12 条路线的对象。
  2.
接着创建出 LampController 对象。  
源码如下:

package com.isoftstone.interview.traffic;

 

public class MainClass {

 

        /**

         * @param args

         */

        public static void main(String[] args) {

               

               /*产生12个方向的路线*/               

               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();

        }

 

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值