2012-01-03 65 views
3

我將模擬交通燈系統。 我創建了擴展JFrame並實現Runnable的Road類。如何訪問Java中的可運行對象中的變量

在run()方法中,我添加了增加每輛車的Y位置的邏輯,現在模擬汽車的運動。 但是現在我需要在移動汽車之前檢查紅綠燈的狀態。

這是我的交通燈類,

import java.util.Random; 

public class TrafficLight implements Runnable { 

volatile boolean stop; 

public TrafficLight(boolean stop) { 
    this.stop = stop; 
} 

@Override 
public void run() { 
    Random randomGenerator = new Random(); 
    while (true) { 
     if (stop) { 
      stop = false; //change current status 
     } else { 
      stop = true; //change current status 
     } 
     try { 
      Thread.sleep(2000 + randomGenerator.nextInt(2000)); 
     } catch (Exception ex) { 
      System.out.println("error"); 
     } 
     } 
    } 
} 

有什麼辦法來檢查這個volatile變量停止,從我的道路等級。

如果不是,請給我建議另一個解決方案來做到這一點。

謝謝。

+0

這是功課?如果是這樣,你應該添加'家庭作業'標籤? – helios 2012-01-03 12:26:48

+2

在'while(true)...'塊中吞下一個'InterruptedException'(這是你對catch塊做的事)是一個壞主意:你的應用程序很難優雅地關閉,因爲循環不會終止。如果你不想處理它,最好把它重新拋出爲'RuntimeException'。 – artbristol 2012-01-03 12:42:20

回答

6

實現停止訪問器。

public class TrafficLight implements Runnable { 

    volatile boolean stop; 

    // Irrelevant code 

    public boolean isStop() { 
    return stop; 
    } 
} 

收到關於Road類構造TrafficLight,並用它來獲得訪問stop變量

public class Road implements Runnable { 

    private TrafficLight trafficLight; 

    public Road (TrafficLight trafficLight) { 
    this.trafficLight = trafficLight;  
    } 

    @Override 
    public void run() { 
    // Irrelevant code 
    if(trafficLight.isStop()) { 
     // do something 
    } 
    } 
} 
+0

非常感謝@安東尼。我幫你解決了這個問題。 – 2012-01-04 05:42:25

0

換句話說,這是否意味着汽車需要聽取交通燈的變化?觀察者設計模式也可能對此有所幫助。

1

道路(或任何需要價值的人)應該可以訪問TrafficLight的實例並詢問它是否爲綠色。你可以提供一個布爾方法。

但是對這個屬性(stop)的訪問應該被保護。 volatile關鍵字並沒有太大的幫助(見下文)。

我應該這樣做:

private synchronized void toogleStopped() { // guarded 
    this.stop = !this.stop; 

} 

public synchronized boolean isStopped() { // guarded 
    return this.stop; 
} 

活動

如果其他一些對象需要對變化做出反應的燈(反應「輕已經改變」事件),使用Observer設計模式正如@TejasArjun所建議的那樣。

volatile爲什麼不幫助

volatile使得Java避免假設變量是不是 「外部」 變化。所以如果一個線程設置它的值(或者之前讀取它),第二次讀取將使用(可能)一個緩存值(已經保存在CPU寄存器中)。 volatile會使Java始終從內存中讀取值。

表示即使使用volatile關鍵字,丟失的更新問題仍然存在。一個線程可以1)讀取2)寫入。另一個線程可以做同樣的事情。他們可以在此爲了做到這一點:

線程1讀取假 線程2讀取錯誤 線程1套真(假設它讀取錯誤) 線程2套真(假設它讀取錯誤)

而這不好:)

所以你必須告訴Java使自動讀取&寫。這就是爲什麼我們可以使用​​關鍵字來確保一個線程同時執行整個同步塊,而不是與另一個線程交錯。

+2

此外,如果您需要像helios指出的那樣自動讀取/更新,另一個選項是使用[AtomicBoolean](http://docs.oracle.com/javase/7/docs/api/java/util/concurrent/原子/ AtomicBoolean.html)。如果只有'TraffigLight'自己設置停止值,則不需要。 – 2012-01-03 12:43:50