2009-07-30 169 views
1

我有一個線程,我需要等待它的結果,這樣的:Java的等待 - 爲多線程問題

t1.start(); 
while (variableModifiedByMyThread == null) { 
    /* do nothing */ 
} 
// "t1" set the value of "variableModifiedByMyThread" 

上面的代碼工作,但不是一個很好的解決方案...

這段代碼是否執行相同的操作(是否等待「t1」線程)?

t1.start(); 
try { 
    t1.join(); 
} catch (InterruptedException e) { 
    e.printStackTrace(); 
} 
// "t1" thread finished 
+2

此處您的第一個代碼示例不是線程安全的。無法保證主線程在不鎖定/同步的情況下會看到變量「variableModifiedByMyThread」所做的更改。你的主線可以永遠旋轉。 – Jon 2009-07-30 21:57:53

回答

4

前者正在等待變量被設置,後者正在等待線程死亡。如果變量被設置之前線程死亡幾乎沒有什麼差別,除了:

  • 昔日的「旋轉」 - 等待的線程在做一些事情(檢查變量)所有的時間 - 很浪費!
  • 後者可能被另一個線程中斷。
+0

你的答案比我的更清楚。 +1 :) – aperkins 2009-07-30 22:10:07

1

你的第二個代碼做什麼是觀看T1,並等待其死亡。一旦t1死亡,它將再次啓動。有關該方法,請參閱javadoc

1

是的,除非你沒有浪費CPU週期通過檢查變量每獲得一次機會。這是一個更好的方法來做到這一點。

這是假定變量只在t1完成時才被修改。如果t1應該修改變量並保持活着狀態,這將不起作用。

順便說一句,你不應該簡單地旋轉像這樣的循環等待。你至少應該在循環內調用Thread.yield();否則在允許任何其他線程運行之前,您可能會循環多次。

編輯:其實,來想想看,一個元素BlockingQueue可能是你真的想要什麼。這聽起來像一個生產者 - 消費者問題(特別是如果你不止一次這樣做),並且BlockingQueue就是爲此而設計的。

0
public class Test{ 
    private final Object lock = new Object(); 
    private Object var = null; 

    public void starThreadAndWaitForOutput(){ 
    Thread t1 = new Thread(new Runnable(){ 
     public void run(){ 
     synchronized(lock){ 
      var=new Object(); 
      lock.notify(); 
     } 
     } 
    }).start(); 

    synchronized(lock){ 
     while(var==null) 
     lock.wait(); 
    } 

    System.out.println("We have the var and thread 1 is still going!"); 
    } 
} 
+1

這不太對,你應該防止虛假的喚醒。 (有關此信息,請參閱java.lang.Object.wait javadoc)。 結果是你應該說: 同步(鎖定){ while(var == null){ 鎖定。等待(); } } – daveb 2009-07-30 21:59:18

+0

你是對的!我提出了建議的修復。 – Charlie 2009-07-30 22:09:19

4

考慮Future秒。這個想法是,你有一些將在「未來某個時候」完成的計算,然後你可以檢查它是否已經完成,或者等待它。

根據JavaDoc:

FutureTask<String> future = 
    new FutureTask<String>(new Callable<String>() { 
    public String call() { 
     return searcher.search(target); 
    }}); 
executor.execute(future); 
0

你可以使用t1.yield()只要你的條件成立暫停線程。