(黑马程序员)学习笔记,交通信号灯系统

交通灯管理系统
需求:
模拟实现十字路口的交通灯管理系统逻辑,具体需求如下:
* 异步随机生成按照各个路线行驶的车辆:
例如:
由南向来去往北向的车辆。。。直行车辆
由南向来去往西向的车辆。。。左转车辆
由南向来去往东向的车辆。。。右转车辆
* 信号灯忽略黄灯,只考虑红灯和绿灯
* 考虑左转车辆控制信号灯,右转车辆不受信号灯控制
* 信号灯控制欲现实生活中相同:南北向车辆交替放行,同方向先直行再左转
* 每辆车通过路口的时间是1秒(可用线程Sleep方法模拟)
* 随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置
* 不要求实现GUI,只考虑系统逻辑是实现,可通过log方式展现运行结果

分析:
1.先分析灯:
通过简单的画图,可以看出共有12条路线。除去4条右转路线,还有4条直行路线和4条左转路线,并且两两成对。
因此程序只需要控制4条路线即可,而且是固定的12个方向。
所以这里使用枚举来列出这12个灯,
* 假设要控制的路线为南向北,南向西,西向东,西向北。
* 通过构造方法获得:当前灯对应的灯,下一次该亮的灯,当前灯的状态
* 需要一个方法向外提供当前灯的状态
* 需要两个方法,一个使当前灯和对应的灯变绿,一个使当前灯胡对应的灯变红并把下一个该亮的的灯变绿

2.分析路和车:
用面向对象的方法分析,路上有车(车应该是路的一个属性),当一个车开走后还要向路上添加新的车辆
* 使用一个集合来保存可变的车辆
* 通过构造方法获得当前方向的路,使用线程为该路添加新车辆,判断当前灯是否为绿色的,如果为绿灯,则指定路线上的车辆通行
* 因为要随机生成各个路线上的车辆,这里用到线程池: 
 ExecutorService threadPool = Executors.newSingleThreadExecutor();
* 车辆开走需要定时器,定时每秒走一辆车,这里使用:
 ScheduledExecutorService timer =  Executors.newScheduledThreadPool(1);


3.信号灯控制器:
信号灯控制器需要确定第一个灯是哪个方向,然后将该灯变成绿色,然后依次间隔一段时间使下一个信号灯变亮
* 通过构造方法确定一个当前灯,并通过灯的方法让其变绿
* 需要一个定时器来控制时间,变换信号灯

4.测试运行:
先向各个方向的路上添加车辆,即开启各个路的线程,这里现将各个方向的路存在数组中,然后for循环依次开启
然后开始信号灯控制,这里只要调用信号灯控制器构造方法

代码:
1.灯,枚举类
package com.interview.traffic;
/*
 * 交通灯:
 * 默认所有方向的灯都不亮,
 * 加入控制方法使绿灯亮,并且对应位置的的灯一起亮
 * 
 * 经过分析,只需要初始化4个方向的灯即可完成信号灯功能(这里初始化的是南向北的灯,南向西的灯,西向东的灯,西向北的灯)
 */
public enum Lamp {

	//南向北的灯(对应的北向南的灯,下一次是南向西的左转灯,当前绿灯不亮)
	South2North("North2South","South2West",false),
	//南向西的灯(对应的北向东的灯,下一次是西向东的直行灯,当前绿灯不亮)
	South2West("North2East","West2East",false),
	//西向东的灯(对应的东向西的灯,下一次是西向北的灯,当前绿灯不亮)
	West2East("East2West","West2North",false),
	//西向北的灯(对应的东向南的灯,下一次是南向北的灯,当前绿灯不亮)
	West2North("East2South","South2North",false),
	North2South(null,null,false),East2West(null,null,false),//其他直行灯
	North2East(null,null,false),East2South(null,null,false),//其他左转向灯
	South2East(null,null,true),East2North(null,null,true),North2West(null,null,true),West2South(null,null,true);//所有右转向灯
	
	private String opposite;//对应的灯
	private String next;//下一次该亮的灯
	private boolean lighted;//当前灯状态
	
	private Lamp(){}
	//根据当前灯获得对应方向的灯,下一次该亮的灯,当前灯状态
	private Lamp(String opposite,String next,boolean lighted){
		this.opposite = opposite; 
		this.next = next;
		this.lighted = lighted;
	}
	//向外提供当前灯状态,返回标志:true为绿灯,false为红灯
	public boolean isGreen(){
		return lighted;
	}
	//绿灯亮,对应的灯也要变绿
	public void turnGreen(){
		this.lighted = true;
		if(opposite!=null){
			Lamp.valueOf(opposite).turnGreen();
			System.out.println(this.name()+"和"+this.opposite+"变绿了");
		}
	}
	//绿灯灭,对应的灯也要灭,然后下一个控制灯变绿
	public Lamp turnRed(){
		this.lighted = false;
		if(opposite!=null){
			Lamp.valueOf(opposite).turnRed();
			System.out.println(this.name()+"和"+this.opposite+"变红了");
		}
		Lamp nextLamp = null;
		if(next!=null){
			nextLamp = Lamp.valueOf(next);
			nextLamp.turnGreen();
		}
		return nextLamp;
	}
}

2.路

package com.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;
//交通灯所在路线
public class Road {

	//很多车, 这里用List来存储,为了面向接口编程
	private List<String> vechicles = new ArrayList<String>();
	//路的名字
	private String name = null;
	
	//没有一条新路的时候,需要知道路的名字
	public Road(String name) {
		this.name = name;
		//用线程来控制路上车的数量,这里使用了线程池
		ExecutorService threadPool = Executors.newSingleThreadExecutor();
		threadPool.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 (Exception e) {
						e.printStackTrace();
					}
					//这里因为要使用的name是与本类中的私有对象相同的外部对象,所以需要用  外部对象名.this.name 的形式来表示
					vechicles.add(Road.this.name + "_" + i);
	
				}
			}
		});
		//定义1个定时器
		ScheduledExecutorService timer =  Executors.newScheduledThreadPool(1);
		timer.scheduleAtFixedRate(
				new Runnable(){
					@Override
					public void run() {
						
						if(vechicles.size()>0){
							//当有车辆的时候看灯是否是绿色
							boolean lighted = Lamp.valueOf(Road.this.name).isGreen();
							//如果是绿色,把车开走
							if(lighted==true){
								System.out.println(vechicles.remove(0)+",该车已经开走");
							}
						}
					}
				}, 
				1, //1单位执行1次(1秒执行1次)
				1, //间隔1单位重复(每隔1秒再次执行)
				TimeUnit.SECONDS//单位为秒
				);
	}
}


3.信号灯控制器

package com.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.South2North;
		//将灯变绿
		currentLamp.turnGreen();
		//使用1个定时器
		ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
		timer.scheduleAtFixedRate(
				new Runnable(){
					public void run(){
						//等待10秒后,将当前灯变成红色,并获取下一个灯
						currentLamp = currentLamp.turnRed();//该方法改变灯的颜色后,返回下一个灯
					}
				}, 
				10,//10秒变灯
				10,//间隔10秒
				TimeUnit.SECONDS);
	}
}

4.测试运行

package com.interview.traffic;
//运行交通灯方法
public class MainClass {

	public static void main(String[] args) {
		//将所有方向的路放在一个数组中
		String[] directions = new String[]{
				"South2North","North2South","East2West","West2East",
				"South2West","West2North","North2East","East2South",
				"South2East","East2North","North2West","West2South"};
		//依次根据路名(路的通向)来向路上添加车辆
		for(String direction : directions){
			new Road(direction);
		}
		//开始控制交通灯
		new LampController();
	}
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值