交通灯管理系统

 

 

 

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

 
  • 异步随机生成按照各个路线行驶的车辆。

例如:

       由南向而来去往北向的车辆—- 直行车辆

       由西向而来去往南向的车辆—- 右转车辆

       由东向而来去往南向的车辆—- 左转车辆

       .....

  • 信号灯忽略黄灯,只考虑红灯和绿灯。
  • 应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。
  • 具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。

基本思想

1、Java的程序设计,我们必须首要掌握面向对象的思想,有了思想,我们才能对案例进行分析,才能对代码的实现有全局的把握。

 

2、其次,程序设计要与现实生活相联想。面向对象的开发,就是对事物进行描述,封装成对象,再调用这些对象完成一些工作。
         
3、面向对象的最基本的原则 :谁拥有数据,谁就应该对外提供操作这些数据的方法。

 

下面我们首先来画一张模拟交通路线的示意图。

 

接着进行面向对象的分析和设计:

 

  • 条路线上都会出现多辆车,路线上要随机增加新的车,在灯绿期间还要每秒钟减少一辆车。

1.设计一个Road类来表示路线,每个Road对象代表一条路线,总共有12条路线,即系统中总共要产生12个Road实例对象。


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


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

 

  • 每条路线每隔一秒都会检查控制本路线的灯是否为绿,一个灯由绿变红时,应该将下一个方向的灯变绿。


1. 设计一个Lamp类来表示一个交通灯,每个交通灯都维护一个状态:亮(绿)或不亮(红),每个交通灯要有变亮和变黑的方法,并且能返回自己的亮黑状态。


2. 总共有12条路线,所以,系统中总共要产生12个交通灯。右拐弯的路线本来不受灯的控制,但是为了让程序采用统一的处理方式,故假设出有四个右拐弯的灯,只是这些灯为常亮状态,即永远不变黑。


3. 除了右拐弯方向的其他8条路线的灯,它们是两两成对的,可以归为4组,所以,在编程处理时,只要从这4组中各取出一个灯,对这4个灯依次轮询变亮,与这4个灯方向对应的灯则随之一同变化,因此Lamp类中要有一个变量来记住自己相反方向的灯,在一个Lamp对象的变亮和变黑方法中,将对应方向的灯也变亮和变黑。每个灯变黑时,都伴随者下一个灯的变亮,Lamp类中还用一个变量来记住自己的下一个灯。


4. 无论在程序的什么地方去获得某个方向的灯时,每次获得的都是同一个实例对象,所以Lamp类改用枚举来做显然具有很大的方便性,永远都只有代表12个方向的灯的实例对象。


5. 设计一个LampController类,它定时让当前的绿灯变红。

 

下面我们来看具体类的实现

 

Road 类:

    对于这个模型,主要用于操作车辆,对应每一天路线,我们都会进该路线上的车辆进行增删操作,即如果该路线是绿灯,则位于该路线最开始的车辆将通过。通过这个行为用删除集合中第一个元素表示。由于在该路线的尾部将会不断的增加车辆,为了更贴近生活,车辆的增加时间间隔用以随机数表示。同时,我们每创建一条路线时,就需要启动在车辆增加和删除功能,故用到多线程。

 

具体代码如下:

package traffic;

import java.util.ArrayList;
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 RoadDemo {
	
	private ArrayList<String>vechicles=new ArrayList<String>();//存储某条路线上的车辆
	private String name=null;
	
	RoadDemo(String name){
		this.name=name;
		//产生一个线程池
		ExecutorService pool=Executors.newFixedThreadPool(1);
		
		//为线程池分配任务,并且将相应的任务分配给线程池里面的线程
	    pool.execute(new Runnable(){
	    	@Override
	    	public void run(){
	    		for(int i=0;i<1000;i++){
	    			try{
	    			Thread.sleep((new Random().nextInt(10)+1)*100);
	    			}
	    			catch(InterruptedException e){
	    				e.printStackTrace();
	    			}
	    			//内部类调用外部类的成员时,用类名+this.变量名
	    			vechicles.add(RoadDemo.this.name+" "+i);
	    		}
	    	}
	    });
	    
	    //创建一个线程调度池
	    ScheduledExecutorService pools=Executors.newScheduledThreadPool(1);
	    
	    //按照一定的速度启动线程和调用相应的任务
	    pools.scheduleAtFixedRate(
	    		new Runnable(){
	    			public void run(){
	    				boolean lighted=LampDemo.valueOf(RoadDemo.this.name).isLight();
	    				//如果当前灯为绿灯,则把当前第一辆车移除
	    				if(lighted){
	    					//打印被移除的灯
	    					System.out.println(vechicles.remove(0)+"   is travling");
	    				}
	    			}
	    		},
	    		1, //设置1s后启动
	    		1, //每个1s启动线程
	    		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 traffic;

public enum LampDemo {
	
	//每个枚举元素各表示一个方向的控制灯
	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 boolean lighted;	//代表是否为绿灯
	private String opposite;	//代表所对应的路线的灯
	private String next;	//代表相邻路线的灯
	
	private LampDemo(String opposite,String next,boolean lighted){
		this.lighted=lighted;
		this.opposite=opposite;
		this.next=next;
	}
	
	//判断当前所对应的交通灯的状态
	public boolean isLight(){
		return this.lighted;
	}
	
	public void Light(){
		//将灯变为绿灯
		this.lighted=true;
		if(opposite!=null)
			//把所对应的路线灯变为绿灯
			LampDemo.valueOf(opposite).Light();
		System.out.println(name()+"所关联的路灯变绿");
	}
	
	//将灯变为红灯
	public LampDemo backLight(){
		this.lighted=false;
		if(opposite!=null)
			//把所对应的路线灯变为红灯
			LampDemo.valueOf(opposite).backLight();
		System.out.println(name()+"所关联的路灯变红灯");
		//注意此处必须为Null,否则,将程序将无法访问
	    LampDemo lamp=null;
		if(next!=null){
			//通过字符串获取相应的枚举成员
			lamp=LampDemo.valueOf(next);
			lamp.Light();
			System.out.println(LampDemo.valueOf(next).name()+"--->"+"路灯由红灯变为绿灯");
		}
		return lamp;
	}
}
 
LampController 类:
1. 整个系统中只能有一套交通灯控制系统,所以,LampController类最好是设计成单例。
2. LampController构造方法中要设定第一个为绿的灯。
3. LampController对象的start方法中将当前灯变绿,然后启动一个定时器,每隔10将当前灯变红和将下一个灯变绿。
  具体代码如下:
package traffic;

import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;

public class LampController {
	
	private LampDemo currentLamp;
	
	LampController(){
		//设置启动
		this.currentLamp=LampDemo.S2N;
		this.currentLamp.Light();
		//定义线程调度池
		ScheduledExecutorService  timer=Executors.newScheduledThreadPool(1);
		timer.scheduleAtFixedRate(
				new Runnable(){
					public void run(){
						LampController.this.currentLamp=LampController.this.currentLamp.backLight();//调用下一个路口的灯,使其变绿
					}
				},
				10,
				10,
				TimeUnit.SECONDS
		);
	}
}
 
MainClass 类:
1.用for循环创建出代表12条路线的对象。
2.接着再获得LampController对象并调用其start方法
   具体代码如下:
package traffic;

public class MainClass {

	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 RoadDemo(directions[i]);
		}
		//产生整个交通灯系统		
		new LampController();
	}
}
 
【最总运行结果】如下:
N2S所关联的路灯变绿
S2N所关联的路灯变绿
S2N 0   is travling
N2W 0   is travling
N2S 0   is travling
S2E 0   is travling
W2S 0   is travling
E2N 0   is travling
S2N 1   is travling
N2S 1   is travling
S2E 1   is travling
N2W 1   is travling
E2N 1   is travling
....
....
S2E 9   is travling
E2N 9   is travling
N2W 9   is travling
W2S 9   is travling
N2S所关联的路灯变红灯
S2N所关联的路灯变红灯
N2E所关联的路灯变绿
S2W所关联的路灯变绿
S2W--->路灯由红灯变为绿灯
S2W 0   is travling
N2E 0   is travling
S2E 10   is travling
E2N 10   is travling
N2W 10   is travling
W2S 10   is travling
S2W 1   is travling
N2E 1   is travling
S2E 11   is travling
N2W 11   is travling
W2S 11   is travling
E2N 11   is travling
S2W 2   is travling
N2E 2   is travling
S2E 12   is travling
E2N 12   is travling
N2W 12   is travling
W2S 12   is travling
......
......
 
最后对交通灯管理系统 的设计与实现做下总结:
    对设计任何一个系统,我们首先要根据其业务需求及描述归纳出其概念模型,将该模型进行分析,归纳,最后总结出出他们的规律,并画出简要模型。在根据整个模型进行面向对象的分析,确定出我们所需要的各个类,在这一步我们可以根据面向对象设计把握一个重要的经验:谁拥有数据,谁就对外提供操作这些数据的方法。利用这个原则对其进行设计。最后写出我们所需的系统,然后进行相应的测试和代码优化。
 
 
以下是对提供的参考资料的总结,按照要求结构化多个要点分条输出: 4G/5G无线网络优化与网规案例分析: NSA站点下终端掉4G问题:部分用户反馈NSA终端频繁掉4G,主要因终端主动发起SCGfail导致。分析显示,在信号较好的环境下,终端可能因节能、过热保护等原因主动释放连接。解决方案建议终端侧进行分析处理,尝试关闭节电开关等。 RSSI算法识别天馈遮挡:通过计算RSSI平均值及差值识别天馈遮挡,差值大于3dB则认定有遮挡。不同设备分组规则不同,如64T和32T。此方法可有效帮助现场人员识别因环境变化引起的网络问题。 5G 160M组网小区CA不生效:某5G站点开启100M+60M CA功能后,测试发现UE无法正常使用CA功能。问题原因在于CA频点集标识配置错误,修正后测试正常。 5G网络优化与策略: CCE映射方式优化:针对诺基亚站点覆盖农村区域,通过优化CCE资源映射方式(交织、非交织),提升RRC连接建立成功率和无线接通率。非交织方式相比交织方式有显著提升。 5G AAU两扇区组网:与三扇区组网相比,AAU两扇区组网在RSRP、SINR、下载速率和上传速率上表现不同,需根据具体场景选择适合的组网方式。 5G语音解决方案:包括沿用4G语音解决方案、EPS Fallback方案和VoNR方案。不同方案适用于不同的5G组网策略,如NSA和SA,并影响语音连续性和网络覆盖。 4G网络优化与资源利用: 4G室分设备利旧:面对4G网络投资压减与资源需求矛盾,提出利旧多维度调优策略,包括资源整合、统筹调配既有资源,以满足新增需求和提质增效。 宏站RRU设备1托N射灯:针对5G深度覆盖需求,研究使用宏站AAU结合1托N射灯方案,快速便捷地开通5G站点,提升深度覆盖能力。 基站与流程管理: 爱立信LTE基站邻区添加流程:未提供具体内容,但通常涉及邻区规划、参数配置、测试验证等步骤,以确保基站间顺畅切换和覆盖连续性。 网络规划与策略: 新高铁跨海大桥覆盖方案试点:虽未提供详细内容,但可推测涉及高铁跨海大桥区域的4G/5G网络覆盖规划,需考虑信号穿透、移动性管理、网络容量等因素。 总结: 提供的参考资料涵盖了4G/5G无线网络优化、网规案例分析、网络优化策略、资源利用、基站管理等多个方面。 通过具体案例分析,展示了无线网络优化中的常见问题及解决方案,如NSA终端掉4G、RSSI识别天馈遮挡、CA不生效等。 强调了5G网络优化与策略的重要性,包括CCE映射方式优化、5G语音解决方案、AAU扇区组网选择等。 提出了4G网络优化与资源利用的策略,如室分设备利旧、宏站RRU设备1托N射灯等。 基站与流程管理方面,提到了爱立信LTE基站邻区添加流程,但未给出具体细节。 新高铁跨海大桥覆盖方案试点展示了特殊场景下的网络规划需求。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值