---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------
定义交通灯的类:
package com.itheima.test.traffic;
/*
* 模拟十字路口交通灯,十字路口总共有12条行驶线路, 每条线路没有有一个交通灯控制车辆的行驶,每一个
* Lamp对象代表一个交通灯,用Lamp模拟交通灯的实现。
* 十字路口12条行驶线路:
* 从南往北(S2N),从南往东(S2E),从南往西(S2W)
* 从北往南(N2S),从北往西(N2W),从北往东(N2E)
* 从西往东(W2E),从西往南(W2S),从西往北(W2N)
* 从东往西(E2W),从东往北(E2N),从东往南(E2S)
* 从南往东(S2E),从东往北(E2N),从北往西(N2W),从西往南(W2S)都是右转,不受红绿灯的影响,可以认为这四个方向上的交通灯一直都是绿灯
* 除了这四个方向的车辆不受交通灯的控制外,其他方向上的车辆都要按照交通灯的规则行驶,可以将这八个方向上的交通灯分为四组:
* (1)从南往北(S2N),从南往北(S2N)受交通灯的控制一致,该方向上的交通灯为绿灯时,其他三组方向上的交通灯为红灯
* (2)从西往东(W2E),从东往西(E2W)受交通灯的控制一致,该方向上的交通灯为绿灯时,其他三组方向上的交通灯为红灯
* (3)从南往西(S2W),从北往东(N2E)受交通灯的控制一致,该方向上的交通灯为绿灯时,其他三组方向上的交通灯为红灯
* (4)从西往北(W2N),从东往南(E2S)受交通灯的控制一致,该方向上的交通灯为绿灯时,其他三组方向上的交通灯为红灯
* 交通灯改变为绿灯或者红灯时,遵循先直行,再左转的原则
*/
public enum Lamp {
/*使用枚举列出各个方向上的交通灯对象*/
S2N(false,"N2S","S2W"),S2W(false,"N2E","E2W"),E2W(false,"W2E","E2S"),E2S(false,"W2N","S2N"),
//下面元素表示与上面的元素的相反方向的灯,它们的相反方向灯和下一个灯应忽略不计!
N2S(false,null,null),N2E(false,null,null),W2E(false,null,null),W2N(false,null,null),
//下面都是右转方向上的等,不是交通灯的控制,假象这四个方向上的交通灯都是绿灯
S2E(false,null,null),E2N(false,null,null),N2W(false,null,null),W2S(false,null,null);
//定义一个变量,用于记录交通灯的状态
private boolean lighted;
//定义一个变量,用于记录当前灯同时为绿的对应方向上的交通灯
private String opposite;
//定义一个变量,用于记录当前交通灯状态改变时,下一个要改变状态的交通灯。灯变红时下一个变绿的灯
private String next;
private Lamp(boolean lighted, String opposite, String next) {
this.lighted = lighted;
this.opposite = opposite;
this.next = next;
}
//判断交通灯的状态
public boolean isLighted(){
return lighted;
}
/**
* 交通灯变为绿灯
* @return void
* */
public void green(){
//修改交通灯的状态为绿灯
this.lighted = true;
//相反方向上的交通灯也变绿灯
if(this.opposite != null){
//获得相反方向上的交通灯对象,并将该交通灯变为绿灯
Lamp.valueOf(opposite).green();
}
System.out.println(toString() + " lamp is green,下面总共应该有6个方向能看到车辆穿过!");
}
/**
* 某个灯变红时,对应方向的灯也要变红,并且下一个方向的灯要变绿
* @return 下一个要变绿的灯
*/
public Lamp red(){
//修改当前交通灯的状态为红灯
this.lighted = false;
//获得相反方向上的交通灯,并变成红灯
if(this.opposite != null ){
Lamp.valueOf(opposite).red();
}
//获得下一个方向上的交通灯
Lamp nextLamp = null;
if(this.next != null){
nextLamp = Lamp.valueOf(next);
System.out.println("绿灯从" + toString() + "-------->切换为" + next);
nextLamp.green();
}
return nextLamp;
}
}
定义路线的类:
package com.itheima.test.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;
/**
* 由于对十字路口交通灯的分析,总共有12个交通灯,对于12条路线,每条路线用Lamp实例对象表示,即系统中总共要产生12个Road实例对象。
* 每条路线上随机增加新的车辆,增加到一个集合中保存。
* 每条路线每隔一秒都会检查控制本路线的灯是否为绿,是则将本路线保存车的集合中的第一辆车移除,即表示车穿过了路口。
*
*/
public class Road {
//定义一个集合,用于存放每条路线上的车辆
private List<String> vechicles = new ArrayList<String>();
//定义一个变量,用于表示路线
private String name;
/*
* 每次创建Road对象的时候,就创建每条路线上的车辆,并检查每条路线上的交通灯是否是绿灯
* 如果是绿灯,就让该路线上的车辆通过,
**/
public Road(String name){
this.name = name;
/*
* 模拟车辆不断随机上路的过程,即在集合中异步添加各个路线上行驶的车辆
* ExecutorService pool = Executors.newSingleThreadExecutor(),创建只有一个线程的线程池对象
* 也就是相当于单线程串行执行所有任务,如果这个唯一的线程因为异常结束,那么会有一个新的线程来替代它。此线程池保证所有任务的执行顺序按照任务的提交顺序执行。
* ExecutorService pool = newFixedThreadPool(int nThreads)创建一个可重用固定线程数的线程池,
* 该线程池可以有nThreads个线程。每次提交一个任务就创建一个线程,直到线程达到线程池的最大大小。
* 线程池的大小一旦达到最大值就会保持不变,如果某个线程因为执行异常而结束,那么线程池会补充一个新线程。
* 如果使用ExecutorService pool = newFixedThreadPool(1);也是创建只有一个线程的线程池,和
* ExecutorService pool = Executors.newSingleThreadExecutor()效果一样
*/
ExecutorService pool = Executors.newSingleThreadExecutor();
//启动线程池里面的一个线程执行
pool.execute(new Runnable(){
@Override
public void run() {
//每隔10秒就在每个线路上创建车辆
for(int i = 0; i<1000;i++){
try {
Thread.sleep((new Random().nextInt(10)+1)*1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
vechicles.add(Road.this.name + "_" + i);
}
}
});
/*
*每隔一秒检查对应的交通灯是否为绿,如果是绿灯,就放行车辆
*/
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(vechicles.remove(0) + " is traversing !");
}
}
}
},
1,
1,
TimeUnit.SECONDS
);
}
}
定义交通灯控制器类:
package com.itheima.test.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.S2N;
currentLamp.green();
/*
* 每隔10秒将当前绿灯变为红灯,并让下一个方向的灯变绿
* 创建一个只有一个线程的ScheduledExecutorService对象
* 该对象的scheduleAtFixedRate(Runnable command, long initialDelay, long period, TimeUnit unit)方法
* 表示创建并执行一个在给定初始延迟后首次启用的定期操作,后续操作具有给定的周期;也就是将在 initialDelay 后开始执行,然后在 initialDelay+period 后执行,接着在 initialDelay + 2 * period 后执行,依此类推。
* */
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
new Runnable(){
@Override
public void run() {
currentLamp = currentLamp.red();
}
},
10,
10,
TimeUnit.SECONDS);
}
}
定义测试类:
package com.itheima.test.traffic;
public class TrafficTest {
/**
* @param args
*/
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 < 12; i++){
new Road(directions[i]);
}
/*产生整个交通灯系统*/
new LampController();
}
}
对于交通灯的类:Lamp还可以这样写
package com.cn.traffic;
/*
* 模拟十字路口交通灯,十字路口总共有12条行驶线路, 每条线路没有有一个交通灯控制车辆的行驶,每一个
* Lamp对象代表一个交通灯,用Lamp模拟交通灯的实现。
* 十字路口12条行驶线路:
* 从南往北(S2N),从南往东(S2E),从南往西(S2W)
* 从北往南(N2S),从北往西(N2W),从北往东(N2E)
* 从西往东(W2E),从西往南(W2S),从西往北(W2N)
* 从东往西(E2W),从东往北(E2N),从东往南(E2S)
* 从南往东(S2E),从东往北(E2N),从北往西(N2W),从西往南(W2S)都是右转,不受红绿灯的影响,可以认为这四个方向上的交通灯一直都是绿灯
* 除了这四个方向的车辆不受交通灯的控制外,其他方向上的车辆都要按照交通灯的规则行驶,可以将这八个方向上的交通灯分为四组:
* (1)从南往北(S2N),从南往北(S2N)受交通灯的控制一致,该方向上的交通灯为绿灯时,其他三组方向上的交通灯为红灯
* (2)从西往东(W2E),从东往西(E2W)受交通灯的控制一致,该方向上的交通灯为绿灯时,其他三组方向上的交通灯为红灯
* (3)从南往西(S2W),从北往东(N2E)受交通灯的控制一致,该方向上的交通灯为绿灯时,其他三组方向上的交通灯为红灯
* (4)从西往北(W2N),从东往南(E2S)受交通灯的控制一致,该方向上的交通灯为绿灯时,其他三组方向上的交通灯为红灯
* 交通灯改变为绿灯或者红灯时,遵循先直行,再左转的原则
*/
public enum Lamp {
/*使用枚举列出各个方向上的交通灯对象*/
S2N(false,"N2S","S2W"),S2W(false,"N2E","E2W"),E2W(false,"W2E","E2S"),E2S(false,"W2N","N2S"),
//下面元素表示与上面的元素的相反方向的灯!
N2S(false,"S2N","N2E"),N2E(false,"S2W","W2E"),W2E(false,"E2W","W2N"),W2N(false,"E2S","S2N"),
//下面都是右转方向上的等,不是交通灯的控制,假象这四个方向上的交通灯都是绿灯
S2E(true,null,null),E2N(true,null,null),N2W(true,null,null),W2S(true,null,null);
//定义一个变量,用于记录交通灯的状态
private boolean lighted;
//定义一个变量,用于记录当前灯同时为绿的对应方向上的交通灯
private String oppositeLamp;
//定义一个变量,用于记录当前交通灯状态改变时,下一个要改变状态的交通灯。灯变红时下一个变绿的灯
private String nextLamp;
private Lamp(boolean lighted, String oppositeLamp, String nextLamp) {
this.lighted = lighted;
this.oppositeLamp = oppositeLamp;
this.nextLamp = nextLamp;
}
//判断交通灯的状态
public boolean isLighted(){
return lighted;
}
/**
* 交通灯变为绿灯
* @return void
* */
public void green(){
//修改交通灯的状态为绿灯
this.lighted = true;
if(this.oppositeLamp != null){
//获得相反方向上的交通灯对象,并将该交通灯变为绿灯
Lamp.valueOf(oppositeLamp).lighted = true;
}
System.out.println(toString() + " lamp is green,下面总共应该有6个方向能看到车辆穿过!");
}
/**
* 某个灯变红时,对应方向的灯也要变红,并且下一个方向的灯要变绿
* @return 下一个要变绿的灯
*/
public Lamp red(){
//修改当前交通灯的状态为红灯
this.lighted = false;
//获得相反方向上的交通灯,并变成红灯
if(this.oppositeLamp != null){
Lamp.valueOf(oppositeLamp).lighted = false;
}
//获得下一个方向上的交通灯
Lamp next = null;
if(this.nextLamp != null){
next= Lamp.valueOf(nextLamp);
System.out.println("绿灯从" + toString() + "-------->切换为" + next);
next.green();
}
return next;
}
}
---------------------- <a href="http://edu.csdn.net"target="blank">ASP.Net+Android+IOS开发</a>、<a href="http://edu.csdn.net"target="blank">.Net培训</a>、期待与您交流! ----------------------
详细请查看:<a href="http://edu.csdn.net" target="blank"> http://edu.csdn.net</a>