2009-09-30 70 views
0
Class Ui{ 
    synchronized update() 
    { 
      do something 
    } 

    synchronized stop() 
    { 
      do something 
    } 
} 

多個線程訪問的上述類的方法..Java線程相關的問題

RunnableUI rm1 = new RunnableUI(); 
    RunnableUI rm2 = new RunnableUI(); 


    Thread rmt1 = new Thread(rm1); 
    Thread rmt2 = new Thread(rm2); 


    rmt1.start(); 
    rmt2.start(); 

和Runnable的UI類是

class RunnableUI implements Runnable 
{ 

    public void run() 
    { 
     Ui u1 = new Ui(); 

     u1.update(20); 

     u1.stop(); 
    } 
} 

我想要做的是停止方法後,被第一個線程調用的第二個線程將等待應該開始執行..

我該怎麼做..

問候, Kaddy

+0

如果你的run()方法中創建用戶界面的實例每個線程然後同步它們是沒有意義的,因爲每個線程將有一個監視器 – Antonio 2009-09-30 20:10:07

回答

0

@Kaddy,你有兩個問題,您發佈的代碼:

  1. 你有UI的多個實例,並
  2. 你鎖定爲每個方法,但它似乎要鎖定整個方法。

讓我解釋一下。首先,快速解釋​​。考慮以下代碼:

class MyClass { 
    synchronized void myMethod() { 
    // do something 
    } 
} 

這基本上是簡寫:

class MyClass { 
    void myMethod() { 
    synchronized (this) { 
     // do something 
    } 
    } 
} 

​​作品如何,如果多個線程試圖在同一實例同步,那麼只有一個被允許同步內一次阻止。當進入內部的線程離開塊時(無論是通過正常執行還是由於異常),其餘的線程之一被允許進入其同步塊。這繼續下去,直到沒有線程試圖獲取該實例的鎖。

因此,對於你的第一個問題:每個線程都有自己的Ui實例。所以線程在不同的實例上同步。你可以通過兩種方式解決這個問題。

要麼份額UI的一個實例:

UI ui = new UI(); 
RunnableUI rm1 = new RunnableUI(ui); 
RunnableUI rm2 = new RunnableUI(ui); 

或者在除UI實例以外的其他鎖定:

class UI { 
    private static final Object LOCK = new Object(); 

    public Object getLock() { 
    return LOCK; 
    } 

    public void update() { 
    synchronized (getLock()) { 
     // do something 
    } 
    } 
    ... 
} 

你的第二個問題。你沒有足夠寬廣的鎖定。如果你選擇一個共享UI實例,試試這個:

class RunnableUI implements Runnable { 
    private final UI _ui; 

    RunnableUI(UI ui) { 
    _ui = ui; 
    } 

    public void run() { 
    synchronized (_ui) { 
     _ui.update(20); 
     _ui.stop(); 
    } 
    } 
} 

如果你選擇一個共享鎖,試試這個:

class RunnableUI implements Runnable { 
    public void run() { 
    UI ui = new UI(); 
    synchronized (ui.getLock()) { 
     ui.update(20); 
     ui.stop(); 
    } 
    } 
} 
1

你想線程以順序執行?

它沒有意義,但在這種情況下,您應該插入一個「rmt1.join();」 (以及必要的異常處理)。

1

我想你想要的是一個Semaphore。信號量保持固定數量的許可證(在你的情況下爲1)。你acquire許可證updaterelease它在stop。如果您需要,我會重新編輯以添加代碼示例。

1

使用ExecutorService

RunnableUI rm1 = new RunnableUI(); 
RunnableUI rm2 = new RunnableUI(); 

ExecutorService processingThread = Executors.newFixedThreadPool(1); 
processingThread.submit(rm1); 
processingThread.submit(rm2); 

processingThread.shutdown(); 

Runnable將被調用,並保持運行,直到出頭呼叫停止或可運行的結束。一旦發生這種情況,下一個Runnable將啓動等。

有了這個,你可以鏈接任意數量的runnables,重新配置服務使用多個線程並行執行等等。它非常靈活。

編輯:我剛剛意識到,根據你的描述,你不想等待第一次runnable停止。如果這是真的,那麼這並沒有達到標準,但是我仍然會放棄它。