我有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) {
}
}
}
}
答案 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
规则)