Java中的多线程阻塞

时间:2014-01-18 22:36:00

标签: java multithreading wait notify

我有类Client和方法,名为listRooms()。

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;

}

我还有类Listener(extends Thread),它监听来自服务器的传入消息。当消息到达时,侦听器线程读取Message(使用ObjectInputStream),然后调用next方法。

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线程调用方法但是从对象LobbyView调用listRooms()(扩展View扩展了JPanel )附加到ClientWindow的对象(扩展JFrame),所以它是不同的线程。我不知道为什么会被阻止。所以Listener显然不能调用processMessage,但我不知道为什么或者我对Java中的线程有一些错误的理解:D

编辑:它还表示监听器线程由于某种原因被阻止...

1 个答案:

答案 0 :(得分:3)

  

问题是它永远等待。在发送@refresh消息

之后,从不调用processMessage()

在我的listRooms()方法调用wait Client时,我processMessage(...)调用了notify() Listener对象对象。对于notify()唤醒另一个线程,它必须在同一个对象实例上。当您拥有synchronized方法时,它会锁定this对象实例。

这两个对象必须共享一个公共锁定对象才能相互发信号。一种方法是将锁定对象传入ClientListener,然后执行以下操作:

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

...

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

编辑:它还表示监听器线程由于某种原因被阻止...

我不知道为什么Listener会被屏蔽,但这不是因为notify()电话。