2013-04-20 21 views
3

我有這個方法需要一個線程作爲參數。我希望這個方法能夠讓一個線程等待,如果沒有一個已經等待,然後在另一個線程進入方法時喚醒,以便它們中的兩個可以交互。我認爲我很接近,但在第一個線程上調用wait()之後,其他線程無法訪問該方法。這裏是我的代碼版本簡約:Java - 在對象上調用wait(),然後允許對象訪問方法

// In the class 'Node' 
public synchronized void trade(Thread thread) 
{ 
    if (!threadWaiting) 
    { 
     threadWaiting = true; 
     synchronized(thread) 
     { 
      try { 
       thread.wait(); 
      } catch (InterruptedException e) {...} 
     } 
    } 
} 

我缺少什麼明顯的道歉,我一直在四處尋找一個答案,但我是新的線程,因此我不知道要尋找什麼。

所以我的問題是,當另一個線程試圖進入交易()他們不能,調試器就在那裏停止。

編輯: 這是關於我問的一些更多的澄清。恐怕我原來的帖子不太清楚。

所以我有一個名爲Node的類和另一個名爲Bot的類。 Bot延伸線程以便可以暫停。在程序開始時創建多個Bot對象,然後啓動,每個Bot將調用Node的trade()方法並將其自身傳遞給方法。如果一個Bot是該方法中的第一個,那麼我希望它的線程在Node上等待,直到另一個Bot出現(等待的Bot將存儲在節點中),此時兩個機器人將進行交互。 下面是我的僞代碼方法更清晰的例子:

// Variable to hold the bot that is waiting. 
private Bot waitingBot = null; 
// Method belonging to Node. 
public synchronized void trade(Bot currentBot) 
{ 
    if (waitingBot == null) 
    { 
     waitingBot = currentBot; 
     waitingBot.wait(); 
    } 
    else 
    { 
     currentBot.interactWith(waitingBot); 
     waitingBot.notify(); 
     waitingBot = null; 
    } 
} 

對不起我原來的職位的措辭。

+0

你希望他們如何互動?如果您想要將數據從一個線程傳遞到另一個線程,可以使用[SynchronousQueue](http://docs.oracle.com/javase/6/docs/api/java/util/concurrent/SynchronousQueue.html) – flup 2013-04-20 12:48:18

+0

你看看['CountdownLatch'](http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/CountDownLatch.html)或['CyclicBarrier'](http:// docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/CyclicBarrier.html)類? – 2013-04-20 13:09:30

回答

1

您的實施存在缺陷。你正在對傳遞的參數進行鎖定,對於所有線程,這些參數都是不同的,所以它們不能與等待通知進行交互。

編輯:我不知道究竟你的目標是,但基於細節,這可能幫助: EDIT2:新增鎖()

private final Lock lck = new ReentrantLock(); 
private final Condition cnd = lck.newCondition(); 
private final AtomicBoolean threadwaiting = new AtomicBoolean(false); 

public synchronized void trade(Thread thread) 
{ 
    lck.lock(); 
    try{ 
    if(threadwaiting.get()){ 
     cnd.signalAll(); 
     threadwaiting.set(false); 
     //perform your task 
    }else{ 
     cnd.await(); 
     threadwaiting.set(true); 
    } 
    } 
    } finally { 
    lck.unlock() 
} 

} 

編輯: 看你的更新後,你應該使用的CyclicBarrier與計數2那麼這應該爲你解決這一切。

+0

這沒有奏效,我仍然得到相同的結果。我已經用更多的信息更新了我的答案,因爲我可能沒有足夠好地解釋自己。 – 2013-04-20 14:54:07

+0

你需要循環屏障。該shld爲你解決它。 – Lokesh 2013-04-20 15:20:41

0

這就像Loki的代碼,但提高

private final Lock lock = new ReentrantLock(); 
private final Condition cnd = lock.newCondition(); 
private final AtomicBoolean threadwaiting = new AtomicBoolean(false); 

public void trade(Thread thread) { 
    lock.lock(); 

    if (threadwaiting.get()) { 
     cnd.signalAll(); 
     lock.unlock(); 
     // perform your task of second thread 
    } else { 
     threadwaiting.set(true); 
     try { 
      cnd.await(); 
      // perform your task of first thread 
     } catch (InterruptedException e) { 
     } finally { 
      threadwaiting.set(false); 
      lock.unlock(); 
     } 
    } 
} 
0

這是一個死循環,因爲當你調用thread.wait();你釋放線程對象鎖。但this對同步方法的對象鎖仍然存在,這就是爲什麼其他人不能輸入它。

相關問題