黑马程序员-模拟交通灯控制系统

本文介绍了一个模拟交通灯控制系统的实现方案,使用Java编程语言,通过多线程技术模拟了真实的十字路口交通状况。该系统包括路线(Road)、路灯(Lamp)及控制器(ControllerLamp)等组件。
------- <a  target="blank">android培训</a>、<a  target="blank">java培训</a>、期待与您交流! ----------
/*
 * 思路分析:
 * 十字路口,按上下左右的方向来分析,一共有12条路线,其中4条右转弯是不受灯控制的,还有8条路线。
 * 在剩余的8条路线中是一一对应的关系,可以理解成4组路线,所以在程序中主要考虑其中4条即可。
 * 但是为了同意操作,假象右转也要看路灯,视为常绿灯。
 *
 * 创建Road类来表示路线,一共有12条路线,所以程序中要创建12个Road的实例对象,每一个Road实例对象代表一条路线,也就是direction中的一个元素表示一条路线的名字
 * 在Road的构造函数中创建两个线程,一个用于模拟随机产生车辆上路,一个用于循环检测路口的路灯。
 *
 * 创建Lamp类表示路灯,每条路线都需要一个路灯来控制,所有Lamp也有12个实例对象,把Lamp类搞成枚举类容易方便。
 * 每个灯应该自己有打开的关闭的功能,还有返回自己状态的功能,所有起码要有这三个方法。
 * 而且做到后面会发现在关闭灯的方法里还要有一个打开下一个灯的作用,不然怎么循环啊。所以关闭的方法应该返回下一个灯,同时还要把下一个灯打开。
 * Lamp的构造函数有三个参数,分别的含义是对应的路灯,下一个路灯,路灯的状态,这很重要。
 *
 * 创建ControllerLamp类来控制路灯之间的循环调节,启动系统控制作用。
 * ControllerLamp里面也有一个定时器,每10秒钟就把当前的路灯给关闭,在调用Lamp关闭的方法同时也打开了下一个路灯。这就是循环的关键。
 *
 * 最后搞个主函数,new12个Road实例,打开控制系统完完啦~\(≧▽≦)/~啦啦啦
 *
 *
 * 总结:
 * 昨天看了张老师讲解的模拟交通控制系统,今天上午上班时把思路整理了出来并把代码给敲出来了,同时也复习了下枚举类和Executors这个东西,
 * 下午又把代码给敲了遍,都是根据自己的理解空手码的,也有一些错误的地方,每写一遍都会暴露出一点小问题,有些迷迷糊糊的地方也就出来了,主要
 * 的几点地方就是Lamp中的black方法和ControllerLamp中的线程任务,最得心应手的是Road中的两个线程任务很有意思,现在想起来我还是
 * 在中午吃完饭后意识到每一个Road表示的是一个一个路线,有12个,可以说就彻底彻底的清晰了。一目了然了。
 * 下午通过手机又写了遍思路整理了遍,晚上回来测试代码还顺利,有几点小错误,尝试了自己几个疑惑的写法没错误,其中就是Lamp中到处神略的this,
 * 还有和name()不是很理解,原来和枚举类有关。所有还要加强枚举类的复习,还是基础的问题。
 *
 * 这是一个软通动力以前的七K月薪的面试题,3天时间做出来就上岗O(∩_∩)O~
 */
//====关键代码===================
public class Road { 
 private String name;
 private List<String> vehicles = new ArrayList<String>();
 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) {
     }
     vehicles.add(Road.this.name + "__" + i);
    }
   }
  });
  /*定时器,每隔一秒判断灯是否为绿,是就让第一辆车通过,实质就是用remove来操作集合中的字符串*/
  ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
  timer.scheduleAtFixedRate(new Runnable() {
   public void run() {
    if (vehicles.size() > 0) {
     /*匿名内部类调用外部成员用-->外部类名+this+成员*/
     boolean lighted = Lamp.valueOf(Road.this.name).isLighted();
     if (lighted == true) {
      /*小车要通过啦*/
      System.out.println(vehicles.remove(0)
        + " is travesing");
     }
    }
   }
  }, 1, 1, TimeUnit.SECONDS);
 }
}
//===============================
package com.isoftstone.interview.traffic;
public enum Lamp {
/*每个元素表示一条路线上的灯,最后4个路线上的灯是假象的,为常绿。其中第一个元素与第5个元素相对应,依次类推*/
 D2U("U2D", "D2L", false), D2L("U2R", "R2L", false), R2L("L2R", "R2D", false), R2D(
   "L2U", "D2U", false), U2D(null, null, false), U2R(null, null, false), L2R(
   null, null, false), L2U(null, null, false), D2R(null, null, true), R2U(
   null, null, true), U2L(null, null, true), L2D(null, null, true);
   /*至于要用字符串而不直接用Lamp的实例表示是因为枚举中的元素对应的灯在后面才出来,编译会报错不能通过,只能通过字符串的形式表示再在后面通过valueOf方法得到对应的灯*/
 private String opposite;//对应的一个灯的字符串表示形石4
 private String next;//下一个灯的字符串表示形式
 private boolean lighted;//灯的状态
 Lamp(String opposite, String next, boolean lighted) {
  this.opposite = opposite;
  this.next = next;
  this.lighted = lighted;
 }
 /*返回路灯的状态*/
 public boolean isLighted() {
  return lighted;
 }
 /*亮灯,表示可以通过*/
 public void light() {
  this.lighted = true;
  Lamp.valueOf(opposite).lighted = true;//应该能看到6个方向的车可以通过,4个右转的加上路线上的一个灯和对应的一个灯
  // if (opposite != null) {
  // Lamp.valueOf(opposite).light();
  // }
 }
 /*熄灯,同时记录下一个灯,让其点亮,以达到循环的效果*/
 public Lamp black() {
  this.lighted = false;
  Lamp.valueOf(opposite).lighted = false;
  if (opposite != null) {
   Lamp.valueOf(opposite).black();
  }
  // nextLamp = Lamp.valueOf(next);
  // nextLamp.light();
  // System.out.println("绿灯从" + name() + "-------->切换为" + next);
  Lamp nextLamp = null;
  if (next != null) {
   nextLamp = Lamp.valueOf(next);
   System.out.println("绿灯从" + this.name() + "-------->切换为" + this.next);
   nextLamp.light();
  }
  return nextLamp;
 }
}
//=================================
public class ControllerLamp {
 private Lamp currentLamp;
 public ControllerLamp() {
  currentLamp = Lamp.D2U;
  currentLamp.light();
  /*定时器功能,每10秒钟循环一次,作用让当前的灯熄灭,调用black方法的同时也点亮了下一个灯,反复循环*/
  ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
  timer.scheduleAtFixedRate(new Runnable() {
   public void run() {
    currentLamp = currentLamp.black();
   }
  }, 10, 10, TimeUnit.SECONDS);
 }
}
//============================
public class MainClass {
 public static void main(String[] args) {
  String[] direction = new String[] { "D2U", "D2L", "R2L", "R2D", "U2D",
    "U2R", "L2R", "L2U", "D2R", "R2U", "U2L", "L2D" };
  /*产生12个Road实例,每一个实例代表一条路线*/
  for (int i = 0; i < direction.length; i++) {
   new Road(direction[i]);
  }
  /*启动交通灯控制系统*/
  new ControllerLamp();
 }
}
------- <a  target="blank">android培训</a>、<a  target="blank">java培训</a>、期待与您交流! ----------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值