2014-01-18 48 views
0

我有類Client和listRooms()方法。在Java中的多線程阻塞

public synchronized RoomInfo[] listRooms() { 
    sendMessage(new Message("@refresh")); 

    try { 
     System.out.println("#1"); 
     wait(); 
     System.out.println("#2"); 
    } catch (InterruptedException e) { 
     e.printStackTrace(); 
     return null; 
    } 

    if(m_RoomListMessage == null) 
     return null; 

    RoomInfo[] rooms = new RoomInfo[ m_RoomListMessage.getInteger(0) ]; 
    for(int i=0; i<rooms.length; i++) { 
     rooms[i] = new RoomInfo( 
       m_RoomListMessage.getString(3*i + 1), 
       m_RoomListMessage.getBoolean(3*i + 2), 
       m_RoomListMessage.getInteger(3*i+3) 
     ); 
    } 

    return rooms; 

} 

我也有類監聽器(擴展線程),它偵聽來自服務器的傳入消息。當消息到達監聽線程讀取消息(使用ObjectInputStream),然後調用下一個方法。

public synchronized void processMessage(Message aMessage) {  
    if(aMessage.type.equals("@roomlist")) { 
     m_RoomListMessage = aMessage; 
     notify(); 
     System.out.println("notificiran xD"); 
     return; 
    } 

    MessageHandler handler = m_MessageHandlers.get(aMessage.type); 
    if(handler == null) { 
     System.out.println("No MessageHandler for: " + aMessage.type); 
     return; 
    } 

    handler.onMessage(aMessage); 
} 

問題是它一直在等待。在我發送@refresh消息後,我的服務器顯示它發送了包含服務器上所有房間列表的消息,processMessage()永遠不會被調用,方法也是從Listener線程調用的,但listRooms()是從對象LobbyView調用的(擴展了View,它擴展了JPanel )附加到ClientWindow的對象(擴展JFrame),所以它是不同的線程。我不知道爲什麼它被阻止。所以監聽顯然不能稱之爲而processMessage,但我不知道爲什麼,或者我有Java線程的一些錯誤的認識:d

編輯:這也充分說明監聽線程被阻塞,出於某種原因...

+0

請創建幷包含允許其複製的問題的最小示例(http://stackoverflow.com/help/mcve)。 – Vulcan

+0

你是什麼'同步',你是誰'等'和'通知'?它看起來非常喜歡完全不同的類。 –

+0

記得接受我的答案,如果它幫助你。謝謝。 – Gray

回答

3

問題是它永遠等待。而processMessage()我發@refresh消息

看來,我認爲你的listRooms()呼叫在Client對象上做wait,而你的processMessage(...)方法是Listener對象上調用notify()後不會被調用。要使notify()喚醒另一個線程,它必須位於同一個對象實例上。如果有​​方法,它將鎖定this對象實例。

這兩個對象必須共享一個通用鎖對象才能夠互相發信號。你可以做到這一點的方法之一是在鎖定對象爲Client都和Listener通過,然後像做:

synchronized (commonLock) { 
    commonLock.wait(); 
} 

...

synchronized (commonLock) { 
    commonLock.notify(); 
} 

編輯:這也預示該聽衆線程由於某種原因被阻止...

我不知道爲什麼Listener會被阻止,不是因爲撥打了notify()

+0

或者甚至可能使用['Lock'](http://docs.oracle.com/javase/1.5.0/docs/api/java/util/concurrent/locks/Lock.html)。附:正如往常一樣,+1 –

+0

我知道它沒有被阻止,因爲那是,因爲當我發送消息刷新時,服務器迴應消息roomlist,並且我在到達時放置了一些打印消息的代碼,並且它打印所有消息在發送@refresh之前到達,之後沒有打印roomlist消息,因此ObjectInputStream從不讀取對象,所以偵聽器線程必須是未知原因的阻塞。 – clzola

+0

@Gray 我在Client類中創建了類CommonLock和字段鎖。然後我把這個代碼 同步(CommonLock.class){lock.wait} 在roomList() 和 同步(CommonLock.class){lock.notify()} INT而processMessage方法。 我得到IllegalMonitorStateException – clzola