------- android培训、java培训、期待与您交流! ----------
业务需求
模拟实现十字路口的交通灯管理系统逻辑,具体需求如下:
Ø 异步随机生成按照各个路线行驶的车辆。
例如:
由南向而来去往北向的车辆 ----直行车辆
由西向而来去往南向的车辆 ----右转车辆
由东向而来去往南向的车辆 ----左转车辆
。。。
Ø 信号灯忽略黄灯,只考虑红灯和绿灯。
Ø 应考虑左转车辆控制信号灯,右转车辆不受信号灯控制。
Ø 具体信号灯控制逻辑与现实生活中普通交通灯控制逻辑相同,不考虑特殊情况下的控制逻辑。
注:南北向车辆与东西向车辆交替放行,同方向等待车辆应先放行直行车辆而后放行左转车辆。
Ø 每辆车通过路口时间为1秒(提示:可通过线程Sleep的方式模拟)。
Ø 随机生成车辆时间间隔以及红绿灯交换时间间隔自定,可以设置。
Ø 不要求实现GUI,只考虑系统逻辑实现,可通过Log方式展现程序运行结果。
分析
1. 十字路口的每个路口的车行驶的方式都有直行,左转,右转3种,所以一共有12条线路,分别是S2N, S2W, E2W, E2S, N2S, N2E, W2E, W2N, S2E, E2N, N2W, W2S
2. 因为一个路口与它相对的路口等灯的信号是一样的,所以这里只需要考虑南边和东边的信号灯,它们对面的灯随着它们的改变就可以
3. 需要的实体有路,车,灯,灯控制器,可以将车存入集合中,将集合装入路的对象中,所以最后一共有三个实体,路,灯,灯控制器
4. 每条路线对应一个灯,四个右转固定是绿灯,其它的每次将一个和它对面变成绿灯,隔10秒后将灯变红,下个灯及它对面的灯变绿
5. 灯可以用枚举来表示,每个枚举对象指定它对面的灯,下一个灯和当前灯的状态
6. 灯控制器里面定义初始路线,并定义定时器将初始路线的灯变红,下一个变绿,不能定义没有指定对面路口灯和下一个灯的Lamp为初始路线
代码示例
1. Road类,里面有添加车辆和移除车辆的两个线程
package com.itcast.trafficschedule;
import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class Road {
// 创建一个集合, 保存车辆, 车辆用String表示
List<String> vehicles = new ArrayList<String>();
// 定义变量保存路的名字
String name;
// 定义构造方法接收路的名字并向路中添加车辆
public Road(String name) {
this.name = name;
// 创建线程来给路面添加车辆
new Thread() {
public void run() {
for (int i = 1; i <= 1000; i++) {
try {
// 1-10秒内随机添加一辆车
Thread.sleep((new Random().nextInt(10) + 1) * 1000);
vehicles.add(Road.this.name + "_" + i);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}.start();
// 创建线程池, 创建线程的第二种方式
// ExecutorService pool = Executors.newSingleThreadExecutor();
// //执行线程往集合中添加车辆
// pool.execute(new Runnable() {
// public void run() {
// for (int i = 1; i <= 1000; i++) {
// try {
// //1-10秒内随机添加一辆车
// Thread.sleep((new Random().nextInt(10) + 1) * 1000);
// vehicles.add(Road.this.name + "_" + i);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
// }
// }
// });
// 如果是绿灯, 每隔一秒让路口的第一辆车通过
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
// 按固定频率开启线程的方法, 这里是每隔一秒执行一次
timer.scheduleAtFixedRate(new Runnable() {
public void run() {
if (vehicles.size() > 0) {
boolean lighted = Lamp.valueOf(Road.this.name).isLighted();
if (lighted) {
System.out.println(vehicles.remove(0) + "通过了路口");
}
}
}
}, 1, 1, TimeUnit.SECONDS);
}
}
2. Lamp枚举类,里面有12条线路的灯
package com.itcast.trafficschedule;
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);
// 定义对面的灯的字符串形式
String opposite;
// 定义下一个灯的字符串形式
String next;
// 定义灯的状态, true为绿灯, false为红灯
boolean lighted;
// 构造方法用于初始化灯的状态
private Lamp(String opposite, String next, boolean lighted) {
this.opposite = opposite;
this.next = next;
this.lighted = lighted;
}
// 得到灯的状态
public boolean isLighted() {
return lighted;
}
// 绿灯亮的方法
public void light() {
// 将当前对象的灯变为绿灯
this.lighted = true;
System.out.println(name() + "是绿灯, 会有6个方向的车通过");
// 将它对面的灯变为绿灯
if (this.opposite != null) {
Lamp.valueOf(opposite).light();
}
}
// 红灯亮的方法
public Lamp blackOut() {
// 将当前灯变红
this.lighted = false;
// 将对面的灯变红
System.out.println(name() + "变成了红灯");
if (this.opposite != null) {
Lamp.valueOf(opposite).blackOut();
}
//
Lamp nextLamp = null;
// 将它的下一个灯变绿
if (this.next != null) {
nextLamp = Lamp.valueOf(this.next);
nextLamp.light();
}
return nextLamp;
}
}
3. 灯控制类, 里面定时改变灯的状态
package com.itcast.trafficschedule;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class LampController {
// 定义当前的灯的对象
Lamp currentLamp;
// 构造方法
public LampController() {
// 将当前灯先设置为红灯
currentLamp = Lamp.S2N;
currentLamp.light();
// 每隔10秒让下一个灯变绿, 当前变红
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(new Runnable() {
public void run() {
// 将当前灯变成红灯, 下一个灯变绿
currentLamp = currentLamp.blackOut();
}
}, 10, 10, TimeUnit.SECONDS);
}
}
4. 执行程序的主类
package com.itcast.trafficschedule;
public class MianClass {
public static void main(String[] args) {
// 创建数组保存12条路线
String[] directions = { "S2N", "S2W", "E2W", "E2S", "N2S", "N2E",
"W2E", "W2N", "S2E", "E2N", "N2W", "W2S" };
// 生成12条线路的对象
for (int i = 0; i < directions.length; i++) {
new Road(directions[i]);
}
// 创建灯控制器
new LampController();
}
}