模擬實現十字路口的交通燈管理系統邏輯
具體需求如下
異步隨機生成按照各個路線行駛的車輛
例如
由南向而來去往北向的車輛
直行車輛
由西向而來去往南向的車輛
右轉車輛
由東向而來去往南向的車輛
左轉車輛
…
信號燈忽略黃燈
只考慮紅燈和綠燈
應考慮左轉車輛控制信號燈
右轉車輛不受信號燈控制
具體信號燈控制邏輯與現實生活中普通交通燈控制邏輯相同
不考慮特殊情況下的控制邏輯
注
南北向車輛與東西向車輛交替放行
同方向等待車輛應先放行直行車輛而後放行左轉車輛
每輛車通過路口時間為
秒(提示
可通過線程Sleep的方式模擬)
隨機生成車輛時間間隔以及紅綠燈交換時間間隔自定
可以設置
不要求實現GUI
只考慮系統邏輯實現
可通過Log方式展現程序運行結果
在這裡面
需要弄三個類Road;Lamp;LampController;mainClass
Road
每個Road對象都有一個name成員變量來代表方向
有一個vehicles成員變量來代表方向上的車輛集合
在Road對象的構造方法中啟動一個線程每隔一個隨機的時間向vehicles集合中增加一輛車(用一個
路線名_id
形式的字符串進行表示)
在Road對象的構造方法中啟動一個定時器
每隔一秒檢查該方向上的燈是否為綠
是則打印車輛集合和將集合中的第一輛車移除掉
package com
taobao
interview;
import java
util
ArrayList;
import java
util
List;
import java
util
Random;
import ncurrent
ExecutorService;
import ncurrent
Executors;
import ncurrent
ScheduledExecutorService;
import ncurrent
TimeUnit;
public class Road {
private String name;
private List<String> vechicles = new ArrayList<String>()
public Road(String name){
this
name = name;
ExecutorService pool = Executors
newSingleThreadExecutor()
pool
execute(new Runnable() {
@Override
public void run() {
for(int i=
;i<
;i++){
try {
Thread
sleep(new Random()
nextInt(
)*
)
vechicles
add(Road
this
name+i)
} catch (InterruptedException e) {
// TODO Auto
generated catch block
e
printStackTrace()
}
}
}
})
ScheduledExecutorService timer = Executors
newScheduledThreadPool(
)
timer
scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
if(vechicles
size()>
&& Lamp
valueOf(Road
this
name)
isLighted())
System
out
println(vechicles
remove(
)+
有車行駛
)
}
}
TimeUnit
SECONDS)
}
}
Lamp
系統中有
個方向上的燈
在程序的其他地方要根據燈的名稱就可以獲得對應的燈的實例對象
綜合這些因素
將Lamp類用java
中的枚舉形式定義更為簡單
每個Lamp對象中的亮黑狀態用lighted變量表示
選用S
N
S
W
E
W
E
N這四個方向上的Lamp對象依次輪詢變亮
Lamp對象中還要有一個oppositeLampName變量來表示它們相反方向的燈
再用一個nextLampName變量來表示此燈變亮後的下一個變亮的燈
這三個變量用構造方法的形式進行賦值
因為枚舉元素必須在定義之後引用
所以無法再構造方法中彼此相互引用
所以
相反方向和下一個方向的燈用字符串形式表示
增加讓Lamp變亮和變黑的方法
light和blackOut
對於S
N
S
W
E
W
E
N這四個方向上的Lamp對象
這兩個方法內部要讓相反方向的燈隨之變亮和變黑
blackOut方法還要讓下一個燈變亮
除了S
N
S
W
E
W
E
N這四個方向上的Lamp對象之外
其他方向上的Lamp對象的nextLampName和oppositeLampName屬性設置為null即可
並且S
N
S
W
E
W
E
N這四個方向上的Lamp對象的nextLampName和oppositeLampName屬性必須設置為null
以便防止light和blackOut進入死循環
package com
taobao
interview;
public enum Lamp {
S
N(
N
S
false
S
W
)
S
W(
N
E
false
E
W
)
E
W(
W
E
false
E
S
)
E
S(
W
N
false
S
N
)
N
S(null
false
null)
N
E(null
false
null)
W
E(null
false
null)
W
N(null
false
null)
W
S(null
true
null)
S
E(null
true
null)
E
N(null
true
null)
N
W(null
true
null)
private String opposite;
private String next;
private boolean lighted;
private Lamp(String oppostie
boolean lighted
String next){
this
opposite = oppostie;
this
lighted = lighted;
this
next = next;
}
public void light(){
lighted = true;
if(opposite!=null){
Lamp oppLamp = Lamp
valueOf(opposite)
oppLamp
light()
}
System
out
println(this
name()+
方向綠燈亮了
可以行駛
)
}
public Lamp black(){
lighted = false;
Lamp nextLamp = null;
if(opposite!=null){
Lamp
valueOf(opposite)
black()
}
if(next!=null){
System
out
println(next)
nextLamp = Lamp
valueOf(next)
nextLamp
light()
}
return nextLamp;
}
public boolean isLighted(){
return lighted;
}
}
LampController
整個系統中只能有一套交通燈控制系統
所以
LampController類最好是設計成單例
LampController構造方法中要設定第一個為綠的燈
LampController對象的start方法中將當前燈變綠
然後啟動一個定時器
每隔
秒將當前燈變紅和將下一個燈變綠
package com
taobao
interview;
import ncurrent
Executor;
import ncurrent
Executors;
import ncurrent
ScheduledExecutorService;
import ncurrent
TimeUnit;
public class LampController {
private Lamp currentLamp;
public LampController(){
currentLamp = Lamp
S
N;
currentLamp
light()
ScheduledExecutorService timer = Executors
newScheduledThreadPool(
)
timer
scheduleAtFixedRate(new Runnable(){
public void run(){
currentLamp = currentLamp
black()
}
}
TimeUnit
SECONDS)
}
}
總結
每條路線上都會出現多輛車
路線上要隨機增加新的車
在燈綠期間還要每秒鐘減少一輛車
設計一個Road類來表示路線
每個Road對象代表一條路線
總共有
條路線
即系統中總共要產生
個Road實例對象
每條路線上隨機增加新的車輛
增加到一個集合中保存
每條路線每隔一秒都會檢查控制本路線的燈是否為綠
是則將本路線保存車的集合中的第一輛車移除
即表示車穿過了路口
每條路線每隔一秒都會檢查控制本路線的燈是否為綠
一個燈由綠變紅時
應該將下一個方向的燈變綠
設計一個Lamp類來表示一個交通燈
每個交通燈都維護一個狀態
亮(綠)或不亮(紅)
每個交通燈要有變亮和變黑的方法
並且能返回自己的亮黑狀態
總共有
條路線
所以
系統中總共要產生
個交通燈
右拐彎的路線本來不受燈的控制
但是為了讓程序采用統一的處理方式
故假設出有四個右拐彎的燈
只是這些燈為常亮狀態
即永遠不變黑
除了右拐彎方向的其他
條路線的燈
它們是兩兩成對的
可以歸為
組
所以
在編程處理時
只要從這
組中各取出一個燈
對這
個燈依次輪詢變亮
與這
個燈方向對應的燈則隨之一同變化
因此Lamp類中要有一個變量來記住自己相反方向的燈
在一個Lamp對象的變亮和變黑方法中
將對應方向的燈也變亮和變黑
每個燈變黑時
都伴隨者下一個燈的變亮
Lamp類中還用一個變量來記住自己的下一個燈
無論在程序的什麼地方去獲得某個方向的燈時
每次獲得的都是同一個實例對象
所以Lamp類改用枚舉來做顯然具有很大的方便性
永遠都只有代表
個方向的燈的實例對象
設計一個LampController類
它定時讓當前的綠燈變紅
這是一個很好的題
收獲很多
From:http://tw.wingwit.com/Article/program/Java/hx/201311/26806.html