java多线程模拟交通灯管理系统

本文实例为大家分享了java多线程模拟交通灯管理系统的具体代码,供大家参考,具体内容如下

一、项目业务逻辑分析

项目需求:模拟实现十字路口的交通灯管理系统逻辑,要求如下:

  • 异步随机生成按照各个路线行驶的车辆,例如由北向南行驶的车辆、由东向南行驶的车辆。
  • 信号灯忽略黄灯,只考虑红灯和绿灯的情况。
  • 左转受信号灯控制,右转车辆不受信号灯控制,其他情况与现实生活的逻辑相同。
  • 注:南北向车辆和东西向方向车辆交替放行,同方向等待车辆应先放行直行车辆,而后再放行左转车辆。
  • 每辆车通过路口所需时间为1秒(提示:可以通过线程的sleep方法模拟)。
  • 随机生成车辆,时间间隔以及红绿灯交换时间自定。
  • 不要求GUI,只考虑系统逻辑实现。可在在终端log方式模拟。

首先了解一下现实中十字路口的交通灯的业务逻辑(为此我大晚上在十字路口仔细观察了半个小时,缺少生活啊。),直接上图吧,直观明了:

额,乍一看有点乱,仔细一想很简单,就是东西南北四条路每条路都有三个去向,左转、右转和直行,这样一个十字路口就有了12个行驶方向。每个方向都有一个指示灯,也就是12个信号灯,如果每个信号灯都单独控制,那就麻烦多了,而且很不科学,得一天24小时堵车。需求第3点说明右转不受信号灯控制,其实现实生活照也是这样,一般右转车辆不受控制的(比较繁忙的路口受控制),随时可以转,也就是说永远是绿色等,想不通为什么这样设计?而 对立面的灯是同步变化的,同时绿或者同时红,这样只需要系统控制一个方向的灯就可以了。最后我们只需要控制四个方向的灯就行了,这里选择了图中标记的①②④③四条路线,只要在改变其中一条路线的信号灯时同步改变对立面的灯为相同信号就行了。另外还要同时把下一个信号灯切换成相反的信号,例如S2W变红时,同时N2E也要变红,并且E2W或W2E变绿。这里我们选择逆时针方向轮循。

二、系统详细设计

根据业务需求分析,需要对象:信号灯、信号灯控制系统、汽车和路线。下面具体分析每个对象所以属性和方法。
信号灯类(Lamp):信号灯只有红和绿两种状态,用boolean变量表示,true表示绿灯,false表示红灯。还要提供切换信号灯状态的方法turnRed和turnGreen。
信号灯控制系统(LampController):控制系统主要负责在规定时间切换红绿灯,并随着此类的创建,整个系统就开始运作,所以把系统启动的实现放在了构造方法内。
汽车(Vihicles):这里只需要体现汽车穿过路口的过程不需要体现移动细节,也就是捕捉路上减少一辆车的过程,所以,这个车并不需要单独设计成为一个对象,用一个字符串表示就可以了。并且车是属于公路的,应该是一种聚合关系,根据拥有数据者应提供访问数据的方法的规律,这里路要提供增减车辆的方法。
路线(Road):每辆汽车不是看到对面的信号灯变绿就可以穿过的,要按照路线上的车队顺序依次通过路口,这个深有体会,堵车有时两次绿灯都过不去路口。

根据以上分析类图设计如下:

类图很简单,可以看出这三个类之间只是简单的关联, Road中要用到Lamp的信号灯状态判断是否放行车辆,LampController负责定时切换Lamp的信号灯状态。具体实现时为了方便有些方法的功能是放在构造方法里实现的。

三、具体实现

Lamp类:

public enum Lamp {
 /**
  * E2W=East to West, N2S=North to South
  * 从南面的交通灯开始,逆时针执行
  */
 //初始状态为红灯
 S2N("N2S","S2W",false),S2W("N2E","E2W",false),
 E2W("W2E","E2S",false),E2S("W2N","S2N",false),
 //对立面红灯
 N2E(null,null,false),N2S(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=green,false=red
 private boolean lighted;
 private String opposite=null;
 private String next=null;

 private Lamp() {}
 /**
  * @param opposite 对面的灯
  * @param nexe   下一个灯
  * @param initLighted 灯的初始状态
  */
 private Lamp(String opposite,String next,boolean initLighted){
  this.opposite=opposite;
  this.next=next;
  this.lighted=initLighted;

 }
 //判断灯的状态
 public boolean getLighted(){
  return lighted;
 }
 //绿灯亮  同时把对面的灯设为绿  下一个灯设为红灯
 public void turnGreen(){
  this.lighted=true;

  //如果对面有灯
  if(opposite!=null){
   Lamp.valueOf(opposite).turnGreen();
  }
 }
 //红灯亮  对立面的灯也变红
 public Lamp turnRed(){
  this.lighted=false;
  Lamp nextGreenLamp=null;
  //对面的灯 同步变化
  if(opposite!=null){
   Lamp.valueOf(opposite).turnRed();
  }
  //下一个灯 绿灯亮
  if(next!=null){
   nextGreenLamp=Lamp.valueOf(next);
   nextGreenLamp.turnRed();
  }
  return nextGreenLamp;
 }
}

Road类:

public class Road {
 //存放每条路上的车辆   车名就表示一辆车
 private List<String> vehicles=new ArrayList<String>();
 private  String roadName=null;
 public Road(String roadName) {
  super();
  //根据路的方向取名,名字和对面的红绿灯同名 E2W表示东向西的路
  this.roadName = roadName;

  //用线程池启动一个线程,随机产生一辆车
  Executors.newSingleThreadExecutor().execute(new Runnable(){
   @Override
   public void run() {
    for(int i=1;i<1000;i++){
     try {
      //每隔1~10秒 随机产生一辆车
      Thread.sleep((new Random().nextInt(10)+1)*1000);
     } catch (InterruptedException e) {
      e.printStackTrace();
     }
     //访问外部类的成员变量
     vehicles.add(Road.this.roadName+"路 第  "+i+" 辆车");
    }
   }

  });
  /*
   * 定义一个计时器 使这条路每隔1s 就检查一次这条路对应的交通灯的状态
   * 如果是绿灯 就每隔1s使离一辆车
   */
  ScheduledExecutorService timer=Executors.newScheduledThreadPool(1);
  timer.scheduleAtFixedRate(new Runnable(){

   @Override
   public void run() {
    //先判断这条路上是否有车
    if(vehicles.size()>0){
     //在判断交通灯状态
     boolean lighted=Lamp.valueOf(Road.this.roadName).getLighted();
     if(lighted){
      //从汽车列表中移除  并提示已通过路口
      System.out.println(vehicles.remove(0)+"通过路口。。。");
     }
    }
   }

  }, 1, 1, TimeUnit.SECONDS);
 }
}

LampController类:

//灯控系统
public class LampController {
 private Lamp currentLamp;

 public  LampController() {
  super();
  //交通灯系统初始化   第一个运行的S2N turn green
  this.currentLamp = Lamp.S2N;
  this.currentLamp.turnGreen();
  //定时器 每个10s 切换一次信号灯状态
  ScheduledExecutorService timer=Executors.newScheduledThreadPool(1);
  timer.scheduleAtFixedRate(new Runnable(){

   @Override
   public void run() {
     currentLamp=currentLamp.turnRed();
   }

  }, 10, 10, TimeUnit.SECONDS);

 }
}

运行结果:

四、总结

本题目整体结构很简单,不涉及复杂的设计模式,重点是对业务逻辑的分析,首先要搞明白交通信号灯的运行机制,如果不考虑右转的情况,简答理解就是东西方向和南北方向的车辆交替放行,同方向等待红灯的车辆先放行直行车辆一段时间,然后再放行左转的车辆。在具体实现上有两个难点:其一就是利用线程设置定时器,实时监控每条路上的信号灯状态和模拟随机在各个方向的路上产生一些车辆,控制系统的任务比较简单只需要定时轮流切换信号灯状态。其二是巧妙的把四个方向的信号灯设计成了一个环形链表,控制系统只需要控制一个信号灯,其他3个就有规律的联动运行了。

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持我们。

(0)

相关推荐

  • java多线程实现交通灯管理系统

    本文实例为大家分享了java多线程实现交通灯管理系统的具体代码,供大家参考,具体内容如下 一. 项目要求 模拟实现十字路口的交通灯管理系统逻辑.详细需求例如以下: 1.异步随机生成依照各个路线行驶的车辆. 比如: 由南向而来去往北向的车辆 ---- 直行车辆 由西向而来去往南向的车辆 ---- 右转车辆 由东向而来去往南向的车辆 ---- 左转车辆 ..... 2.信号灯忽略黄灯,仅仅考虑红灯和绿灯. 3.应考虑左转车辆控制信号灯,右转车辆不受信号灯控制. 4.详细信号灯控制逻辑与现实生活中普通

  • java多线程模拟交通灯管理系统

    本文实例为大家分享了java多线程模拟交通灯管理系统的具体代码,供大家参考,具体内容如下 一.项目业务逻辑分析 项目需求:模拟实现十字路口的交通灯管理系统逻辑,要求如下: 异步随机生成按照各个路线行驶的车辆,例如由北向南行驶的车辆.由东向南行驶的车辆. 信号灯忽略黄灯,只考虑红灯和绿灯的情况. 左转受信号灯控制,右转车辆不受信号灯控制,其他情况与现实生活的逻辑相同. 注:南北向车辆和东西向方向车辆交替放行,同方向等待车辆应先放行直行车辆,而后再放行左转车辆. 每辆车通过路口所需时间为1秒(提示:

  • Java多线程模拟银行系统存钱问题详解

    目录 一.题目描述 二.解题思路 三.代码详解 多学一个知识点 一.题目描述 题目:模拟一个简单的银行系统,使用两个不同的线程向同一个账户存钱. 实现:使用特殊域变量volatile实现同步. 二.解题思路 创建一个类:SynchronizedBankFrame,继承JFrame类 写一个内部类Bank 定义一个account变量,来表示账户. deposit():一个存钱的方法 getAccount():显示账户余额的方法. 写一个内部类Transfer,实现Runnable接口 在run方法

  • java多线程模拟抢红包功能

    今天有朋友问我一道面试题,有5个人抢5个红包,可重复抢,用多线程程序实现,实现方式有多种,分享一下我的思路:应用了阻塞队列的特性. /** * Created by zhanglinqiang on 2016/6/23. */ public class MyTest { public static void main(String[] args) throws InterruptedException { LinkedBlockingQueue<LuckyMoney> luckyMoneys

  • Java多线程模拟电影售票过程

    用多线程模拟电影售票过程(Java实训) 实训目的: 多线程的实现.线程同步 实训要求: 总票数和售票窗口数由键盘输入,用每个线程处理一个窗口的售票. Test.java package program5; import java.util.Scanner; public class Test { public static void main(String[] args) { // TODO Auto-generated method stub Scanner sc=new Scanner(S

  • java多线程模拟实现售票功能

    铁道部发布了一个售票任务,要求销售1000张票,要求有3个窗口来进行销售,请编写多线程程序来模拟这个效果. 1 线程类 测试方法: public static void main(String[] args) { MyThread t1 = new MyThread("窗口1"); MyThread t2 = new MyThread("窗口1"); MyThread t3 = new MyThread("窗口1"); t1.start(); t

  • Java多线程模拟售票程序和线程安全问题

    Java中线程部分知识中,售票程序非常经典.程序中也有一些问题存在! 需求:模拟3个窗口同时在售100张票. 问题1:为什么100张票被卖出了300张票? 原因:因为tickets是非静态的,非静态的成员变量数据是在每个对象中都会维护一份数据的,三个线程对象就会有三份. 解决方案:把tickets票数共享出来给三个线程对象使用.使用static修饰. 问题2: 出现了线程安全问题 ? 线程安全问题的解决方案:sun提供了线程同步机制让我们解决这类问题的. java线程同步机制的方式: 方式一:同

  • Java多线程编程小实例模拟停车场系统

    下面分享的是一个Java多线程模拟停车场系统的小实例(Java的应用还是很广泛的,哈哈),具体代码如下: Park类 public class Park { boolean []park=new boolean[3]; public boolean equals() { return true; } } Car: public class Car { private String number; private int position=0; public Car(String number)

  • Java实现多线程模拟龟兔赛跑

    Java多线程模拟龟兔赛跑,供大家参考,具体内容如下 笔者利用Java多线程技术,将兔子和乌龟的跑步以两个线程的方式模拟出来,以达到一个初步的效果. 题目如下:路程总距离为35米 兔子:每秒跑5米,每跑10米,休息2秒: 乌龟:每秒跑3米,不休息. 所用工具 JDK1.8+IntelliJ IDEA 2020.1 代码 Race.java:(线程类,通过new出来的对象的不同线程名,然后分别模拟兔子和乌龟的跑步) package task; import org.omg.Messaging.SY

  • Java多线程中线程的两种创建方式及比较代码示例

    1.线程的概念:线程(thread)是指一个任务从头至尾的执行流,线程提供一个运行任务的机制,对于java而言,一个程序中可以并发的执行多个线程,这些线程可以在多处理器系统上同时运行.当程序作为一个应用程序运行时,java解释器为main()方法启动一个线程. 2.并行与并发: (1)并发:在单处理器系统中,多个线程共享CPU时间,而操作系统负责调度及分配资源给它们. (2)并行:在多处理器系统中,多个处理器可以同时运行多个线程,这些线程在同一时间可以同时运行,而不同于并发,只能多个线程共享CP

随机推荐