Java在Object.wait()之前调用Object.notify()

时间:2013-11-08 11:12:10

标签: java multithreading concurrency wait

我有2个线程用于传输,1个用于重放 我只想在RXThread上收到消息时才发送一条消息。我已经使用了wait()和notify(),并且为了防止在wait()之前发出通知,我这样做,但它只在调试中运行时才有效,尽管RX线程不发送消息。

private boolean stopped = false;


class StubTxtask implements Runnable {

    public void run() {
        try {

            // Sends all messages in sequence
            for (int i=0; i<txMsgSeq.getMessagesCount(); i++) {
            }
                if (syncRxTx) {
                    synchronized (syncObj) {
                        while(!stopped) {
                            syncObj.wait();
                    }
                    }

                }
                System.out.println("************ "+ i + "/" + txMsgSeq.getMessagesCount());
                pcs.sendMsg((GeneratedMessage)txMsgSeq.getMessage(i));
                if (!syncRxTx) {
                    Thread.sleep(1000);
                }
            }

        } catch (Exception e) {

        }
    }
}


class StubRxtask implements Runnable {

    public void run() {
        while (true) {
            try {
                // Wait for a message() 
                TncMessage msg = (TncMessage) pcs.waitMsg(connInt);
                System.out.println(msg.toString());
                // Add the message to the RX Sequence
                rxMsgSeq.addMessage(msg);

                System.out.println(rxMsgSeq.getMessagesCount());

                if (syncRxTx) {
                    TncHeader header;
                    Method invokeGetHeader;
                    try {
                        invokeGetHeader = msg.getClass().getMethod("getHeader", null);
                        header = (TncHeader) invokeGetHeader.invoke(msg, null);
                        if (header.getType() != EnumMessageType.ACK) {
                            synchronized (syncObj) {
                                stopped = true;
                                syncObj.notify();
                            }

                        }


                    } catch (Exception e) {
                        System.err.println("ERROR - Impossible to find or invoke getHeader() method on msg");
                    }


                }
                stopped = false;

            } catch (Exception e) {

            }
        }
    }
}

3 个答案:

答案 0 :(得分:0)

如果它只在调试中正常工作,这通常是因为时序问题而发生的,这在调试模式下是不同的。

据我了解您的代码,使用Phaser可满足您的要求。移相器就像一个障碍:它会导致所有线程等待,直到所有线程都在等待它,除了它是可重用的。由于现在两个线程都在等待相应的其他线程到达,因此您不再需要stopped构造或同步(所有内容都由Phaser处理)。

替换

if (syncRxTx) {
  synchronized (syncObj) {
    while(!stopped) {
      syncObj.wait();
    }
  }
}

if (syncRxTx) {
  phaser.arriveAndAwaitAdvance();
}

if (header.getType() != EnumMessageType.ACK) {
  synchronized (syncObj) {
    stopped = true;
    syncObj.notify();
  }
}

if (header.getType() != EnumMessageType.ACK) {
  phaser.arriveAndAwaitAdvance();
}

注意:与同步对象一样,Phaser应声明为final。

答案 1 :(得分:0)

使用信号量进行同步,因为这类锁处理“早期通知”。

Semaphore sem = new Semaphore(0);

runConsume() {
  .. sem.aquire(1); // will block if nothing avaiable
}

runProduce() {

  // receivedMessage
  .. sem.release(1);
}

答案 2 :(得分:0)

如果您在另一个帖子中使用while循环中的变量并希望获取新数据,则必须使用volatile声明它(检查visibility规则)