一,異步隨機生成按照各個路線行駛的車輛。
例如:
由南向北的車輛----直行車輛
由西向南的車輛----右轉車輛
由東向南的車輛---左轉車輛
二,信號燈忽略黃燈,只考慮紅燈和綠燈。
三,左轉的車輛要受交通燈控制,右轉車輛不受信號燈控制。四,信號燈的控制邏輯和現實 現實中的交通燈控制邏輯相同,不考慮特殊情況下的控制邏輯。
注:南北向的車輛與東西向的車輛交替放行,同方向等待的車輛應先放行直行車輛,然後再放行左轉車輛。
五,每輛車通過路口的時間爲1秒。
六,隨機生成車輛,及定時改變交通燈狀態。
需求分析和設計
首先,分析路口中車輛行駛的方向,用以下的圖例來描述各個車輛的行駛方向:
上圖是演示的一個十字路口,並有12個行駛方向。
一,東南西北直行方向的同時,汽車還可以向左轉;即相對的方向有兩個行駛方向;
那麼四個方向就有了8條行駛方向。
二,由於汽車始終可以向右行駛,所以又轉的交通燈始終爲綠。此處就有4條行駛方向。
經過以上分析,抽象出以下幾個類:路,交通燈,汽車,交通燈控制器。
對類的設計:
汽車的設計:
一,汽車的主要操作是添加到路中,或者綠燈時移除出路。所以只要用一個隨機數來描述汽車就可以了。
路的設計:
一,路上的汽車是有多個的,所以要用集合來接收汽車。
二,路上的汽車是隨機出現的,所以要程序在隨機的時間增加一輛車。
三,如果路燈爲綠時,則在綠燈時間內,將第一輛車移出。
四,因爲交通燈是每個一定時間就改變的,所以路也要有一個功能,在每個一定時間久檢查交通燈的,車輛是否可行駛。
燈的設計:
注:此處忽略黃燈,因爲黃燈是紅燈和綠燈之間轉換的一個緩衝,所以忽略也不會對系統有影響。
一,因爲有12個行駛方向,所以就要有12個對應方法的燈。
二,每一個等都只能有一個,而不是每一次new都是一個新的,所以燈的類型設計爲枚舉,保證唯一。
三,燈都要有是否是亮的,所以燈要有一個屬性來描述狀態:(亮(綠燈)或不亮(紅燈)),還要有一個亮燈的方法,一個滅燈的方法。
四,由於向右行駛的方向總是可以行駛的,是不受控制的,但爲了統一處理方式,就假設出4個右轉的燈,
並將這些燈設置爲總是可以通行的。
五,其他8個方向中,都是相對出現的,所以只要控制4組燈就可以了,而每一組燈都是相對應的燈,所以只要用4個燈控制就可以了。
當前燈和對應燈亮,時間過之後呢,當前燈滅,下一個燈亮。依次這樣執行。
燈的控制器的設計:
一,控制器要控制燈,所以控制器一有一個燈的屬性,通過它類控制燈。
二,因爲控制器是每個一定的時間纔去改變的燈的,所以燈要有一個定時器。
類的編碼:
路的代碼:
一,增加車輛;
二,定時檢查交通燈的情況;
三,綠燈時,移出車輛。
package com.itheima.traficdemo;
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;
/**
* 路
* 實現方式:
* 1,Executors的newSingleThreadExecutor方法,獲得ExecutorService 執行權服務對象。來執行這個線程器,
* 隨機產生汽車。
* 2,再利用Executors獲取定時器對象,並且調用scheduleAtFixedRate來執行定時功能!
* @author wuyong
*
*/
public class Road {
private String name;
private List vechicals = new ArrayList();
public Road(String name){
this.name = name;
//以下是模擬現實中,路上出現的車輛。
//JDK1.5的新功能,是java的狀態併發庫。線程池。類似以數據庫連接池。已啓動就存在線程。空閒則使用。
//ExecutorService,相當於線程池。必須記住Executors來獲得線程池。
ExecutorService pool = Executors.newSingleThreadExecutor();
//啓動線程
pool.execute(new Runnable() {
@Override
public void run() {
for (int i = 0; i < 1000; i++){
try {
//用隨機值來模擬現實中的隨機出現車輛。
Thread.sleep((new Random().nextInt(10) + 1) * 1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
//內部類要調用本類的成員變量,必須要用類名.this.內部類的同名變量!或者是方法的final局部變量或者final參數
//將車輛添加到交通工具集合中。
vechicals.add(Road.this.name + "..." + (i + 1));
}
}
});
//定義一個定時器。
//指定每隔多長時間,檢查交通燈的狀態,如果交通燈是綠的,則對應方向的車前行。
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
//指定定時器要做的任務
new Runnable() {
@Override
public void run() {
if (vechicals.size() > 0) {
//檢查當前燈是否是綠色的。true表示綠色,可以通行。
boolean isLighted = Lamp.valueOf(Road.this.name).isLighted();
if (isLighted) {
//vechicals.remove(0)返回的是被移出的那個元素
System.out.println(vechicals.remove(0) + " 向前行駛。。。");
}
}
}
},
//多長時間開始執行指定的任務
1,
//隔多長時間繼續執行指定的任務
1,
//指定的時間間隔的時間單位,用TimeUnit來指定!!
TimeUnit.SECONDS);
}
}
燈的代碼:
一,燈的狀態;
二,亮燈的方法;
三,滅燈的方法。
package com.itheima.traficdemo;
/**
* 交通燈枚舉類
* 實現方式:
* 1,交通燈鎖具有的屬性,
* 1,交通燈的顏色,
* 2,交通燈的對應的燈,
* 3,交通燈的下一個燈
* 2,交通燈的方法:
* 1,獲得交通燈的顏色,
* 2,將交通燈的顏色變爲綠色,
* 3,將交通燈的顏色變爲紅色。
* @author wuyong
*
*/
public enum Lamp {
//因爲有12種方向,所以定義了12個燈
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),
W2S(null,null,true),S2E(null,null,true),E2N(null,null,true),N2W(null,null,true);
private Lamp(String opposite,String next,boolean lighted){
this.opposite = opposite;
this.next = next;
this.lighted = lighted;
}
//燈的狀態,true爲綠,false爲紅
private boolean lighted;
//當前燈對應的燈。
//注:不能講Lamp作爲對應的燈,因爲變量要使用,必須是先聲明,再使用。而當前燈的對應燈如果作爲構造函數的參數,必須先聲明,而當前燈可能還不存在。
private String opposite;
//當前燈的下一個燈
private String next;
//獲得當前燈的狀態,true爲綠色,false爲紅色。
public boolean isLighted() {
return this.lighted;
}
//將燈,變爲綠色
public void linght() {
this.lighted = true;
//如果當前的燈,有對應的燈,則也將對應的燈變成綠色。如果不判斷,則會出現死循環,或是報異常。
//枚舉可以通過枚舉的名字來獲得對應的元素。
if (opposite != null) {
System.out.println("現在的綠燈是===========" + name());
Lamp.valueOf(opposite).linght();
}
}
//將當前燈變爲紅色,將下一個燈變爲綠色,並返回
public Lamp black(){
this.lighted = false;
this.lighted = true;
//如果當前的燈,有對應的燈,則也將對應的燈變成紅色。
if (opposite != null) {
Lamp.valueOf(opposite).black();
}
//如果當前燈有下一個燈,則將下一個燈變綠色
Lamp nextLamp = null;
if (next != null) {
nextLamp = Lamp.valueOf(next);
nextLamp.linght();
}
return nextLamp;
}
}
交通燈控制器的代碼:
一,每隔一定時間,改變交通燈的狀態。
package com.itheima.traficdemo;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
/**
* 燈的控制器
* 實現方式:
* 1,Executors用執行器,newScheduledThreadPool(1)的線程池獲取ScheduledExecutorService對象;
* 2,用獲取到的定時器線程對象,調用scheduleAtFixedRate方法,執行定時執行任務
* @author wuyong
*
*/
public class LampControler {
//當前燈
private Lamp currentLamp;
//控制等的狀態
public LampControler(){
this.currentLamp = Lamp.S2N;
currentLamp.linght();
//定義計時器
ScheduledExecutorService timer = Executors.newScheduledThreadPool(1);
timer.scheduleAtFixedRate(
//控制器間隔執行的內容
new Runnable() {
@Override
public void run() {
currentLamp = currentLamp.black();
}
},
10,//計時器開始的時間
10, //任務執行的間隔時間
TimeUnit.SECONDS);
}
}
測試類的代碼:
package com.itheima.trafficdemo;
/**
* 交通燈測試類
* @author wuyong
*
*/
public class TrafficMainDemo {
/**
* @param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
//將12個方向存儲到數組中,然後再循環實例化
String[] directions = {
"S2N","S2W","E2W","E2S",
"N2S","N2E","W2E","W2N",
"W2S","S2E","E2N","N2W"};
for (String direction : directions) {
new Road(direction);
}
//實例化交通燈控制器。
new LampControler();
}
}
---------------------- <a href="http://www.itheima.com"target="blank">ASP.Net+Unity開發</a>、<a href="http://www.itheima.com"target="blank">.Net培訓</a>、期待與您交流! ----------------------