package com.itheima.trafficlight;
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;
public class Road
{
/*创建用来存放车辆的集合*/
private List vechicles = new ArrayList();
/*名称属性代表走向*/
private String name =null;
/*构造方法通过传入的名称产生该名称代表的走向的Road对象*/
public Road(String name){
this.name = name;
ExecutorService pool = Executors.newSingleThreadExecutor();
/*
* Executors是一个工具类,主要用来创建和管理线程
* newSingleThreadExecutor()
* -----创建一个使用单个 worker 线程的 Executor,以无界队列方式来运行该线程
* 返回类型是ExecutorService 接口的实现类提供的方法
* shutdown()并不是终止线程的运行,而是禁止在这个Executor中添加新的任务
* execute(Runnable command) 将一个Runnable的实现类的实例作为参数传入,执行相应线程。
* execute是ExecutorService的父接口Executor的唯一的方法 ,根据多态用ExecutorService
* 来指向实现类对象,所以调用execute的时候就是调用对应指向的实现类中的execute方法
* */
pool.execute(new Runnable(){//用内部类直接实现Runnable并将其实例传给execute来执行
public void run(){
for(int i=1;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);
/*
* ScheduledExecutorService也是ExecutorService的实现类 ,可安排在给定的延迟后运行或定期执行的命令
* 其方法scheduleAtFixedRate(Runnable command,
long initialDelay,
long period,
TimeUnit unit)
* 创建并执行一个在给定初始延迟后首次启用的定时操作,后续操作具有给定的周期;也就是将在 initialDelay 后开始执行
* 然后在 initialDelay+period 后执行,接着在 initialDelay + 2 * period 后执行,依此类推。
* 参数:
command - 要执行的任务
initialDelay - 首次执行的延迟时间
period - 连续执行之间的周期
unit - initialDelay 和 period 参数的时间单位
* */
timer.scheduleAtFixedRate(
new Runnable(){
public void run(){
if(vechicles.size()>0){
TrafficLight currentLight = TrafficLight.valueOf(Road.this.name);
boolean green = currentLight.isGreen();
if(green){
System.out.println(vechicles.remove(0) +TrafficLight.getNames()[currentLight.ordinal()]);
}
}
}
},
1,
1,
TimeUnit.SECONDS);
}
}
package com.itheima.trafficlight;
public enum TrafficLight
{ /*下面的四个是受控制系统控制每隔10秒自左向右依次由红变绿并循环的枚举元素*/
S2N("N2S","S2W",false),S2W("N2E","E2W",false),E2W("W2E","E2S",false),E2S("W2N","S2N",false),
/*下面元素受上面的元素的控制,随着上面一组相对方向的灯变化,它们不用控制别的灯的状态所以,前两个参数为null*/
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);
/*当前灯是否为绿,是为true*/
private boolean green;
/*与当前灯状态相同的红绿灯*/
private String oppositeLight;
/*当前灯变红时下一个变绿的灯*/
private String nextLight;
/*走向名称列表*/
private static String[] names = {"南向北直走","南向西左拐弯","东向西直走","东向南左拐弯",
"北向南直走","北向东左拐弯","西向东直走","西向北左拐弯",
"南向东右拐弯","东向北右拐弯","北向西右拐弯","西向南右拐弯"};
/*通过构造方法,在得到每个走向的红绿灯时初始化它们的三个属性*/
private TrafficLight(String oppositeLight,String nextLight,boolean green){
this.oppositeLight = oppositeLight;
this.nextLight = nextLight;
this.green = green;
}
/**
* 可以获取当前灯的红绿状态
*/
public boolean isGreen(){
return green;
}
public static String[] getNames(){
return names;
}
/**
* 当前受控制系统控制的灯由红变绿,并将相对方向的灯也设置为绿灯
*/
public void setGreen(){
green = true;
if(oppositeLight != null){
//将相对方向的灯同时设为绿灯
TrafficLight.valueOf(oppositeLight).setGreen();
}
System.out.println(names[this.ordinal()]+ "绿灯亮啦,该走向的车辆可以通行了!!!");
}
/**
* 当前受控制系统控制的灯由绿变红,同时将相对方向的灯也由绿变红 ,
* 并按顺序让下一个受控制系统控制的灯由红变绿
* @return 下一个要变绿的灯
*/
public TrafficLight setRed(){
System.out.println(names[this.ordinal()]+"要变红灯啦");
this.green = false;
if(oppositeLight != null){
TrafficLight.valueOf(oppositeLight).setRed();
}
TrafficLight nextGreenLight = null ;
if(nextLight != null){
nextGreenLight = TrafficLight.valueOf(nextLight);
nextGreenLight.setGreen();
}
return nextGreenLight;
}
}
代码:
package com.itheima.trafficlight;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
public class ControlSystem
{
private TrafficLight currentLight;
/*控制系统构造方法*/
public ControlSystem(){
/*控制系统初始化时,先让南向北走的红绿灯变绿*/
currentLight = TrafficLight.S2N;
currentLight.setGreen();
/*每隔10秒将当前绿灯变为红灯,并让下一个方向的灯变绿*/
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(new Runnable(){
public void run(){
currentLight = currentLight.setRed();
}
},
10,
10,
TimeUnit.SECONDS);
}
}
4)MainThread
主线程需要创建代表12条走向的Road对象,并
代码 :
package com.itheima.trafficlight;
public class MainThread
{
/**
* @param args
*/
public static void main(String[] args) {
/*主线程需要创建代表12条走向的Road对象,并分别启动一个线程*/
String [] directionNames = new String[]{
"S2N","S2W","E2W","E2S","N2S","N2E","W2E","W2N","S2E","E2N","N2W","W2S"
};
for(int i=0;i
执行结果:
北向南直走绿灯亮啦,该走向的车辆可以通行了!!!
南向北直走绿灯亮啦,该走向的车辆可以通行了!!!
S2E_1南向东右拐弯
W2S_1西向南右拐弯
S2N_1南向北直走
E2N_1东向北右拐弯
S2E_2南向东右拐弯
N2W_1北向西右拐弯
S2N_2南向北直走
N2S_1北向南直走
E2N_2东向北右拐弯
南向北直走要变红灯啦
北向南直走要变红灯啦
北向东左拐弯绿灯亮啦,该走向的车辆可以通行了!!!
南向西左拐弯绿灯亮啦,该走向的车辆可以通行了!!!
S2W_1南向西左拐弯
N2E_1北向东左拐弯
E2N_3东向北右拐弯
S2W_2南向西左拐弯
N2E_2北向东左拐弯
N2W_2北向西右拐弯
S2E_3南向东右拐弯
N2W_3北向西右拐弯
W2S_2西向南右拐弯
S2W_3南向西左拐弯
S2E_4南向东右拐弯
N2E_3北向东左拐弯
E2N_4东向北右拐弯
南向西左拐弯要变红灯啦
北向东左拐弯要变红灯啦
西向东直走绿灯亮啦,该走向的车辆可以通行了!!!
东向西直走绿灯亮啦,该走向的车辆可以通行了!!!
E2W_1东向西直走
W2E_1西向东直走
E2W_2东向西直走
W2E_2西向东直走
E2W_3东向西直走
W2E_3西向东直走
N2W_4北向西右拐弯
E2W_4东向西直走
W2E_4西向东直走
W2S_3西向南右拐弯
W2E_5西向东直走
S2E_5南向东右拐弯
W2E_6西向东直走
S2E_6南向东右拐弯
E2W_5东向西直走
E2N_5东向北右拐弯
N2W_5北向西右拐弯
W2S_4西向南右拐弯
东向西直走要变红灯啦
西向东直走要变红灯啦
西向北左拐弯绿灯亮啦,该走向的车辆可以通行了!!!
东向南左拐弯绿灯亮啦,该走向的车辆可以通行了!!!
E2S_1东向南左拐弯