------- android培训、java培训、期待与您交流! ----------
交通灯管理系统的项目需求:
模拟实现十字路口的交通灯管理系统逻辑,具体需求如下:
异步随机生成按照各个路线行驶的车辆。
例如:
由南向而来去往北向的车辆 ---- 直行车辆
由西向而来去往南向的车辆 ---- 右转车辆
由东向而来去往南向的车辆 ---- 左转车辆
。。。
信号灯忽略黄灯,只考虑红灯和绿灯。
应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。
具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。
注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。
每辆车通过路口时间为1秒(提示:可通过线程Sleep的方式模拟)。
随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置。
不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。
思考:
写描述路的类(张老师这里用的是普通类,我感觉也可以用Enum类)
2,描述路的类里面有对应的灯,每条路上都有各自对应的灯,所以有个灯的属性,构造方法中接收进来。
3,路上面会有车不定时的开过来,建立一个集合,构造方法中不定时的往集合中添加车辆(字符串表示),1~10秒,
可以使用随机数,,也使用到了并发工具包中的Executors(执行类),相当于开启多线程,执行。
4,构造方法中继续使用并发工具包中的类,,判断如果公路上面有车,并且该公路对应的灯是绿色的状态,那么就从集合中删除一个元素,相当于通过了一辆车。
使用并发工具包,主要是因为除了可以建立线程外,还可以设定每隔多长时间就执行一次Runnable里面的run方法,在这里可以设定每隔1秒就检查一次该
路上面所对应的灯是否为绿色状态,绿色就删除元素。。。
写描述灯的类(使用的是Enum类)
1,4个方向,每个方向3个灯,一共12个灯,其中4个右转的灯设置为常亮状态,不用管,剩下8个灯,这8个灯都是两两对应的,也就是只设置4个灯的变红变绿就可以了。
而对应的4个灯是根据设置好的4个灯的变化而变化的。
2,灯有个亮或不亮的属性,有返回该灯亮或不亮的的方法。。。。构造函数中接收该属性。
3,灯有对应的灯。。。构造函数中接收该属性。
4,灯有自己对应的下一个灯是哪一个,,,,构造函数中接收该属性。
5,4个右转的灯接收的参数是:没有对应的灯null,没有下一个灯null,常亮true;
6,4个跟随另外4个变红变绿的灯接收的参数是:对应灯null,下一个灯null,常亮false;
7,4个受控制器控制的灯接收的参数是:对应灯,对应灯的名字。。下一个灯,下一个灯的名字。常亮false;
8,定义灯亮的方法,如果有对应的灯,将对应的灯也变为绿色。
9,定义灯灭(变红)的方法,如果有对应的灯,将对应的灯也变红。。。判断是否有对应的下一个灯,如果有对应的下一个灯,将下一个灯变为绿色状态,
并返回下一个灯。
注:枚举类中的构造函数都是私有的,,,,枚举类可以通过valueOf(String str)获取枚举类中的子类。
写描述控制器的类
1,构造函数中:先获取一个受控制器控制的灯的实例对象。。。。。定义一个灯类型的类变量,将获取到的灯赋值给变量。
2,将该灯变为绿色。
3,使用并发运行包中的类,,,每隔10秒中,将该灯关闭,然后将返回的下一个灯赋值给灯类型的类变量,这样每隔10秒就会变换一次绿灯。
写演示的类:
1,首先得有12条公路,,,,所以new出来12条公路的实例对象,而每条路对应各自的灯的名字。(字符串表示形式)
2,有了公路的类,公路类中的构造方法已经运行,,方法中有一个线程不定时的往集合中添加元素,而另外一个线程判断该公路对应的路灯是否是绿色的。
如果是绿色的就删除元素,,,,相当于公路上不定时的开上来车,而碰到绿灯就开过去。。。。
3,有了公路类还得让灯开始运行起来,new一个控制器的实例对象,这样每隔10秒就会变换一次绿灯了,没每个绿灯对应的都是6条线路,右转外4条,相对方向2条。
(试验了一下不new控制器的实例对象,也就是不开启控制器,,,有4条线路的车在通行,4条右转的,,,,,,)
用到的包和类:
包:import java.util.concurrent.Executors(并发运行包)
Executors类:
此包中所定义的 Executor、ExecutorService、ScheduledExecutorService、ThreadFactory 和 Callable 类的工厂和实用方法。
static ExecutorService newSingleThreadExecutor()//普通线程池
创建一个使用单个 worker(工作) 线程的 Executor(执行),以*队列方式来运行该线程。
static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)//调度线程池
创建一个线程池,它可安排在给定延迟后运行命令或者定期地执行。
java.util.concurrent
接口 ExecutorService:
Executor 提供了管理终止的方法,以及可为跟踪一个或多个异步任务执行状况而生成 Future 的方法。
这个接口中的接口功能说明不好理解,但是他的父类的接口说明就好理解了:
他的父类接口是Executor:
执行已提交的 Runnable 任务的对象。此接口提供一种将任务提交与每个任务将如何运行的机制
(包括线程使用的细节、调度等)分离开来的方法。通常使用 Executor 而不是显式地创建线程。
例如,可能会使用以下方法,而不是为一组任务中的每个任务调用 new Thread(new(RunnableTask())).start():
父类接口Executor中的方法:
void execute(Runnable command)
在未来某个时间执行给定的命令。
java.util.concurrent
接口:ScheduledExecutorService:
一个 ExecutorService,可安排在给定的延迟后运行或定期执行的命令。
ScheduledFuture<?> scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)
创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期;也就是将在 initialDelay 后开始执行,
然后在 initialDelay+period 后执行,接着在 initialDelay + 2 * period 后执行,依此类推。
java.util.Random:随机数类
全部的代码,以后没事多写几遍,不会的可以过来看看:
路:
package com.itheima.test;
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.TimeUnit;
/*
* 每个Road对象代表一条路线,总共有12条路线,即系统中总共要产生12个Road实例对象。
* 每条路线上随机增加新的车辆,增加到一个集合中保存。
* 每条路线每隔一秒都会检查控制本路线的灯是否为绿,是则将本路线保存车的集合中的第一辆车移除,即表示车穿过了路口。
* */
import java.util.concurrent.ScheduledExecutorService;
public class Road {
//每条路线上随机增加新的车辆,增加到一个集合中保存。
private List<String> vechicles = new ArrayList<String>();
//每条路的名字
private String name = null;
public Road(String name){
this.name = name;
//模拟车辆不断随机上路的过程。
ExecutorService pool = Executors.newSingleThreadExecutor();
pool.execute(new Runnable(){
@Override
public void run() {
for(int x = 0;x<1000;x++){
//随机1-10秒,公路上就多一辆车
try {
Thread.sleep((new Random().nextInt(10)+1)*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
vechicles.add(Road.this.name + " : " + x);
}
}
});
//每隔一秒检查对应的灯是否为绿,是则放行一辆车
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(new Runnable(){
@Override
public void run() {
if(vechicles.size()>0){
//这条路对应的路灯是不是绿的
boolean lighted = Lamp.valueOf(Road.this.name).isLighted();
if(lighted){
System.out.println(Road.this.name + " : ?" + vechicles.remove(0) + " 移除公路的名字:第几辆车");
}
}
}
},
1,
1,
TimeUnit.SECONDS);
}
}
灯:
package com.itheima.test;
public enum Lamp {
/*每个枚举元素各表示一个方向的控制灯*/
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 Lamp(String opposite,String next,boolean lighted){
this.opposite = opposite;
this.next = next;
this.lighted = lighted;
}
/*当前灯是否为绿*/
private boolean lighted;
/*与当前灯同时为绿的对应方向*/
private String opposite;
/*当前灯变红时下一个变绿的灯*/
private String next;
public boolean isLighted(){
return lighted;
}
//某个灯变绿时,它对应方向的灯也要变绿
public void light(){
this.lighted = true;
if(opposite !=null)
Lamp.valueOf(opposite).light();
System.out.println(name() + " : " + "这个灯变绿了,下面应该看到6个方向的车穿过");
}
//某个灯变红时,对应方向的灯也要变红,并且下一个方向的灯要变绿
// @return 下一个要变绿的灯
public Lamp blackOut(){
this.lighted = false;
if(opposite!=null)
Lamp.valueOf(opposite).blackOut();
Lamp nextLamp = null;
if(next!=null){
System.out.println(name()+"--->"+next+" : "+ " 这个路上的绿灯变成了下条路上的绿灯");
nextLamp = Lamp.valueOf(next);
nextLamp.light();
}
return nextLamp;
}
}
控制器:
package com.itheima.test;
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.S2N;
currentLamp.light();
/*每隔10秒将当前绿灯变为红灯,并让下一个方向的灯变绿*/
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(new Runnable(){
@Override
public void run() {
System.out.println("每隔10秒将绿灯变为红灯");
currentLamp = currentLamp.blackOut();
}
},
10,
10,
TimeUnit.SECONDS);
}
}
测试类:
package com.itheima.test;
public class MainClass {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
/*产生12个方向的路线*/
String[] directions = {"S2N","S2W","E2W","E2S",
"N2S","N2E","W2E","W2N",
"S2E","E2N","N2W","W2S"};
for(int x =0;x<directions.length;x++){
new Road(directions[x]);
}
/*产生整个交通灯系统*/
new LampController();
}
}
总结:很抽象,学习到了新的工具包和新的类,没有具体讲到底是怎么用的,只能凭着演示的方法模糊的知道他的大概用处。
希望快些进入黑马,能学会独立看API文档。