黑马程序员_【总结】_ Pa_交通灯管理系统

本文介绍了一种交通灯管理系统的实现方案,模拟实现十字路口的交通灯逻辑。系统包括路线、红绿灯、控制器等核心对象,详细说明了这些对象的功能及交互逻辑。文中还提供了具体的代码实现,帮助读者理解整个系统的运作流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

交通灯管理系统


----------  android培训 java培训 、期待与您交流! ---------- 

---------------------------------------------------------------------------------------------------------------------------------------------
项目名称:
 
                      【【【交通灯管理系统】】】
模拟实现十字路口的交通灯管理系统逻辑,具体需求如下


1、 异步随机生成按照各个显露行驶的车辆
例如:
由南而来去往北的车辆--- 直行车辆
由西而来去往南的车辆--- 右转车辆
由懂而来去往南的车辆--- 左转这两
。。。
2、 信号灯忽略 黄灯,只考虑红灯和绿灯


3、应考虑左转车辆控制信号灯,右转车辆不受信号灯控制


4、 具体信号灯控制逻辑与现实生活中的交通灯控制逻辑相同
不考虑特殊情况下的控制逻辑
注:南北车辆与东南车辆交替放心,
同方向等待车辆应放行直行车辆而后放行左转车辆


5、每辆车 通过路口时间为1秒(提示:可通过线程sleep的方式模拟)


6、随机生成车辆时间建个以及 红绿等叫特时间建个自定,可以设置


7、不要求实现GUI, 只考虑系统逻辑实现,可通过LOG方式展现程序运行结果
----
个人感觉
1、找出关键对象
2、实现单个对象相关功能
3、改进相互间需要的部分功能
4、进行测试、调节 
----
配图


分析:

1、 该项目涉及到:灯、车、路、控制器。
2、该十字路口,每个方向的车辆会有3种可能的行驶方向,得出合计 有12条路线、同时也是12只灯
3、由此可见,设计到了:红绿灯(题目不要求黄灯)、灯的变频控制器、交通工具、路线。
由于本项目只考虑系统逻辑实现,不要求实现交通工具运行移动的过程,只捕捉交通工具穿过路口的过程
同时,交通工具运行到某一条路线上,需要观察该路线上的红绿灯,
并且需要知道该自己在路线是否助于第一位置,才能决定是否通过。
由此可见,交通工具在本项目中,只是充当路线上的一个元素,
1、路线让第一个通过马路(依次),
2、路线随机生成后来的交通工具
3、本项目有 12条路线

4、如此:本项目设计到的(对象) 功能类: 1、路线 2、红绿灯、3、控制器   4测试类
5、灯,逻辑上有12只红绿灯,联系实际生活中,假设右转的4只灯为常绿
并且 直线上的红绿灯会两两对立(这组灯同时变绿灯--另外组则同时变红灯)--与生活中一致了。
如此一来,就只剩下4只灯(--对应4只灯--4只常绿灯)
在这种设计思维下,编写类的时候,应该初始化:
1、对面的灯
2、下一个灯
3、灯的状态
6、控制器,让灯在规定的时间一到,就变色。应该用一个 变频定时器来完成
1、默认控制一个灯
2、变频定时器 定时变灯
7、测试类 
1、创建 12条路线 
2、创建 控制器,开启功能
---
思路
1、class Road 路线
1、路线应该初始化时就指定名称
2、路线随机时间add 一辆车
构造函数不能直接创建线程--调用Thread.sleep();
1、使用线程池,创建线程池对象
2、创建线程
1、设定 随机睡眠时间时间
2、add 新车
3、移除车辆--通过十字路口
1、需要用线程池对象
2、创建一个定时器-按频率移除
1、移除时要进行判断--路线上是否有车
1、判断红绿灯的状态--绿灯才移除

2、enum Lamp 红绿灯
1、创建时记得是 enum
2、创建12只灯  分三组
3、3个关键成员变量:
1、当前等的对面的灯
2、当前灯的下一个灯
3、当前灯的状态
4、根据成员变量生成相关的方法
1、返回对面灯的方法
2、返回下一个灯的方法
3、返回当前灯状态的方法
4、表示等状态的方法
1、亮状态    >>对应- 绿
1、当前等亮的时候--对面的等同步变亮
2、黑状态          >> 对应- 红
1、当前等黑的时候--对面的等同步变黑
2、当前等变黑--同步下一组灯  变亮
5、由此得出 构造方法时,需要初始化3个关键元素。

3、class LampContorller 变频控制器
1、默认控制一组灯
2、构造方法初始化这只灯为   4组灯的某一个(不能是其他灯)
3、构造方法初始化这只灯状态 为   1、亮  2、黑
4、继续构建一个变频定时器,进行灯的状态的切换
1、其实很简单,就是设定一个时间         时间-->变黑-->时间-->变亮      无限循环
2、记住用Executors 线程池  的对象和方法来完成 

4、class MainClass 启动功能测试类
1、new 出12条线路
2、new 控制器-->  开启 交通灯测试
3、可以把12只灯 放入一个数组--方便new 出12条线路
----------
具体代码:
--
【】交通灯项目-1------Road 路线

public class Road {
	//R-1 首先是一个集合 表示每条路线上的车辆
	private List<String> vehicles = new ArrayList<String>();
	//R-2 每条路     应该有个名字
	private String roadName = null;
	//R-2-1 通过构造函数,使每创建一条路线的时候,就指定一个名字
	public Road(String roadName){
		this.roadName = roadName;
		
		
		//r-3 不能在构造方法中直接Thread.sleep();所以new一个线程池
		ExecutorService pool = Executors.newSingleThreadExecutor();
		//r-3-1 execute执行 new Runnable 这个内部类
		pool.execute(new Runnable(){
			@Override//r-3-2 覆盖 run方法
			public void run() {
				//r-3-2-1 假设每条路上最多999辆车
				for(int i=1 ;i<1000 ;i++ ){
					
					try {
				//r-3-2-3 随机生成一个1-10的数组*1000 就是秒  在这个时间里后 完成添加
						Thread.sleep((new Random().nextInt(10)+1)*1000);
					} catch (InterruptedException e) {
						e.printStackTrace();
					}
					//r-3-2-2 添加 交通工具 到集合
					vehicles.add(Road.this.roadName + "_" + i);
					//内部类访问外部类:1 外部类用final 修饰变量 2、重名时候 用类名.this.变量名
				}
			}
		});//command>>   Runnable 线程    
		// pool.execute>>>end
		//r-4 定时器
		ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
			//r-4 定时器 执行一次,或者循环执行:
			//timer.schedule(command, delay, unit)  只执行一次 下面这个是按频率执行
			//timer.scheduleAtFixedRate(command, initialDelay, period, unit)
			//4个参数分别是;任务、循环频率、多久执行一次、前2者的度量单位(秒、分、时等)
		timer.scheduleAtFixedRate(
		//r-4-1  4个参数分别是:1功能代码、2、1 ,3、1、  4设定前2者为秒
				new Runnable(){
					@Override// 功能代码:
					public void run() {
						//r-4-2表示有车辆
						if(vehicles.size()>0){
							//r-4-3 假如 是绿灯
							//boolean lighted = true;
							//【】RL-1   Lamp.valueOf(name) 获取到当前路线的灯 并 调用isLighted 判断黑亮状态
							boolean lighted = Lamp.valueOf(Road.this.roadName).isLighted();
							if(lighted){
								//r-4-4是绿灯就 让第一辆车通行--就是移除 remove 会返回被移除的元素
								System.out.println("this car:"+vehicles.remove(0)+"---  is traversing ---");;
							}
						}
					}}, 
				1, 
				1, 
				TimeUnit.SECONDS); // end
	}
}
//【】RL-1     代表Road 完成并且 Lamp 完成 后
//Road  end



【】交通灯项目-2----Lamp  红绿灯

public enum Lamp {
	//              N
	//          W         E 
	// 		S 


	//L-1   12个枚举值
//	S2N,S2W,E2W,E2S,//A 正面 - 主功能
//	N2S,N2E,W2E,W2N,//b 对面
//	S2E,W2S,N2W,E2N;//c  常绿灯	
	
	//[L-14]&&[L-12]&&[L-9]&& [L-1]     12个枚举值
	S2N("N2S","S2W",false),S2W("N2E","E2W",false),E2W("W2E","E2S",false),E2S("W2N","S2N",false),//A
		//L-2  仅仅是建立枚举值》》S2N
		//L-9 仅仅是设定 对面灯》》S2N("N2S")
		//L-12 设定灯的 [下一个灯]和  [默认黑亮状态]、》》S2N("N2S","S2W",false)
		//[L-14]把所有等都设置完毕--三个参数,右拐常绿
	N2S(null,null,false),N2E(null,null,false),W2E(null,null,false),W2N(null,null,false),//b
	S2E(null,null,true),E2N(null,null,true),N2W(null,null,true),W2S(null,null,true);//c
	//L-10  构造方法   获取对面的灯
		//L-12 给构造方法添加  下一个灯、默认黑亮参数
	//Lamp(String oppsite){   //传递Lamp oppsite 要报错   通过传递String 表示名字来解决
	private Lamp(String oppsite,String next,boolean lighted){ //参数:对应灯、下一个灯、默认黑亮状态
		this.oppsite = oppsite;
		this.next = next;
		this.lighted = lighted;
	}// L-10、L-12   end
	
	//L-2  交通灯就应该有一个[灯的状态]----表示是亮黑是黑(亮绿,黑红)
	private boolean lighted;
	//L-6 A [对面的灯]  的名字
	private String oppsite;
	//L-13 定义[下一个灯]的名字
	private String next;
	 
	
	//L-8 判断这个灯的状态  ,是亮黑是黑?
	public boolean isLighted(){
		return lighted;
	}
	//L-3 知道是黑是亮后 对面的灯需要同步变化、:
		//L-4  亮状态
	public void light(){
			// this.lighted=true;
			//L-7  的A中的灯亮,则对面的灯同步变亮
			oppsite.light();
			//这里很容易形成死循环,应该通过构造方法设计为,A对应B, B没有对应的,不形成循环。


		this.lighted = true;
		if(oppsite != null){ //A有对应的灯  才亮, 着时候B 没有对应的,就不会亮
			//L-11 构造方法获取到名字以后给枚举,枚举就能返回枚举值对象,再调用亮灯
			Lamp.valueOf(oppsite).light();
			//oppsite.light();
		}
		System.out.println("this Lamp "+name() +"------>> to Green   共有6发方向可以通行" );
	}
		//L-5  黑 状态
	public Lamp blackOut(){
		this.lighted=false;
		//L-15 同//L-7 正面的灯变黑,对面的也变黑。
		if(oppsite != null){ 
			Lamp.valueOf(oppsite).blackOut();
		}
			//L-16 这个灯变黑,则下一个灯 则 变亮--变绿
	//			if(next != null){ 
	//				Lamp.valueOf(next).light();//Lamp end
	//			}
		//LC-1 控制器改进代码
		Lamp nextLamp = null ;
		if(next != null){ 			
			nextLamp = Lamp.valueOf(next);
			System.out.println("【this Green Lamp  :"+name() +"------>>  to :    " +next+"】");
			nextLamp.light();//Lamp end
		}
		//LC-2 让该方法 在同步变黑的时候,返回下一个灯
		return nextLamp;
	}
}
//Lamp end




 
 【】交通灯项目-3---------LampController 灯的控制器

public class LampController {
	//1、 灯的控制器,肯定要控制一个灯
	private Lamp currentLamp;
	public LampController(){
		//2、初始化当前灯线路、状态
		currentLamp = Lamp.S2N;
		currentLamp.light();
		//3、灯是按照规律来变化的,所以要设计一个 频率定时器
		ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
		//3-1 4参数 设定频率为10秒,Run功能10运行一次
		timer.scheduleAtFixedRate(
				new Runnable(){
					public void run(){
						//3-2 应该设计这个灯变黑后,下个等变绿,并且再次调用的时候,是把绿变黑。
						//3-3修改 Lamp 类L-16 为:LC-2  currentLamp 具有记忆功能 
							// blackOut 变黑,并返回下一个灯 所以currentLamp 是下一个的, 这样就循环起来了。
						System.out.println("10秒一次来了");
						currentLamp = currentLamp.blackOut();
					}
				}, 
				10, 
				10, 
				TimeUnit.SECONDS);
	}
}
//LampController  end





【】交通灯项目-4 ------MainClass 测试类
public class MainClass {
	public static void main(String[] args) {
		//1、new 出12 条路线 
		//2、new出控制器
		//1-1
		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 Test_R(directions[i]); 
		}
		//模拟交通灯 runing:
		new LampController();
	}
}//MainClass  end

----------
细节问题:
---
1、concurrent 包,对线程和线程池的使用
以前没学过,目前了解来说
构造方法中不能直接创建线程,通过concurrent 里的对象能够达到相同目的
Executor: 并发      执行已提交的 Runnable 任务的对象  的接口
Executors:  多线程
static ExecutorService newSingleThreadExecutor():
创建单个线程
static ExecutorService newFixedThreadPool(int nThreads) :
创建线程池
static ScheduledExecutorService newScheduledThreadPool(): 
创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
ScheduledExecutorService:可安排在给定的延迟后运行或定期执行的命令   的接口
ScheduledFuture<?> schedule(Runnable command, long delay, TimeUnit unit) :
创建并执行在给定延迟后启用的一次性操作。

 ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit
创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期; 


TimeUnit unit :是代表long delay或者long initialDelay 的时间单位的 是一个枚举 值是:天、时、分、秒等




2、本项目中细节代码
1、
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();
					}
					vehicles.add(Road.this.roadName + "_" + i);
				}
			}
		});

1、拿到线程池的对象
2、调用execute 来创建线程
3、execute方法的参数 采用内部类完成
1、线程 Runnable必须覆盖 run 方法
1、Thread.sleep((new Random().nextInt(10)+1)*1000); 生成随机睡眠时间
2、vehicles.add(Road.this.roadName+ "_" + i); 添加了一个新的交通工具
2、
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
		timer.scheduleAtFixedRate(
				new Runnable(){
					public void run() {
						if(vehicles.size()>0){
							//boolean lighted = true;
							boolean lighted = Lamp.valueOf(Road.this.roadName).isLighted();
							if(lighted){
								System.out.println("this car:"+vehicles.remove(0)+"---  is traversing ---");;
							}
						}
					}}, 
				1, 
				1, 
				TimeUnit.SECONDS); // end


1、拿到定时器对象
2、通过对象 的scheduleAtFixedRate 方法实现 频率定时器
3、参数为 线程、频率时、功能运行时、前2者世间单位
1、线程 Runnable必须覆盖 run 方法
1、判断当前路线的交通工具是否有车
1、判断当前等的状态-是黑还是亮
1、移除集合第一个元素--达到第一辆车通过十字路口。
3、
public void light(){
		this.lighted = true;
		if(oppsite != null){ 
			Lamp.valueOf(oppsite).light();
		}
		System.out.println("this Lamp "+name() +"------>> to Green   共有6发方向可以通行" );
	}


1、设定 状态    lighted 为 true  表示亮
2、有对面关系,则让对面同亮--枚举设定只有单对面(A>>>>b  , b>>>> null)
4、
public Lamp blackOut(){
		this.lighted=false;
		if(oppsite != null){ 
			Lamp.valueOf(oppsite).blackOut();
		}
		Lamp nextLamp = null ;
		if(next != null){ 			
			nextLamp = Lamp.valueOf(next);
			System.out.println("【this Green Lamp  :"+name() +"------>>  to :    " +next+"】");
			nextLamp.light();//Lamp end
		}
		return nextLamp;
	}	


1、当前灯为黑--对面等同步为黑
2、当前灯为黑--下一组灯同步为亮
3、把下一组等提取到判断外

5、
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);

1、12组灯  分三组
1组:主实现功能
1、包含3个参数
1、下一组灯
2、对面的灯
3、等的状态
2组:1组对面灯
3组:常绿灯
6 对应5
private Lamp(String oppsite,String next,boolean lighted){   
		this.oppsite = oppsite;
		this.next = next;
		this.lighted = lighted;
	}	

1、构造函数进行初始化状态
2、初始化 参数:对面灯、下一个灯、黑亮状态  



3、其他需要注意的方法

Thread.sleep(1000): 线程方法睡眠1000毫秒
(new Random().nextInt(10)+1): 随机生成1-10的数字


4、用到的生词
Road: 路 
Lamp: 灯
isoftstone: 软通动力 官网
Interview: 面试 
traffic: 灯 
Vehicles: 交通
execute 执行 
lighted 点亮、亮
oppsite 对应的  
controller 控制器
current 当前的
direction 方向   
light
blackOut


-------
运行结果:




设定的第一个灯是S2N   
运行到这里,  已经是一个轮回了。

无限循环执行。

上述代码和上述图片结果有轻微不同。 不影响功能的演示。







---------------------------------------------------------------------------------------------------------------------------------------------
----------  android培训、  java培训 、期待与您交流!----------


----------------------------------------------
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值