我有一个发送SNMP命令并侦听陷阱的程序。
我的第一种方法协调SNMP的发送。一旦他完成发送,我需要他等到他收到收到陷阱的通知,这样他才能继续跑。现在,我试图通过同步全局对象来做到这一点,但它不起作用,我不确定它对我来说是理想的解决方案。
public synchronized int loginUser(ScopedPDU pdu) throws IOException
{
loginUserManager = new LoginUserManager();
pdu = buildPdu();
// send command
errorStatus = snmpManager.snmpSend(pdu);
if (errorStatus == SnmpManager.SNMP_PASS)
{
// Wait for traps
synchronized(syncObject)
{
// read global variable status to see if it's no longer in progress
while(status == TrapStatus.INPROGRESS)
{
try {
System.out.println("Waiting for login to be done");
syncObject.wait();
System.out.println("We received a notify");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
} //(errorStatus == SnmpManager.SNMP_PASS)
else
{
return TrapStatus.FAIL;
}
System.out.println("Returning status");
return status;
}
我的第二种方法是接收陷阱(并在与第一种方法不同的线程上运行)并获得我想要的正确状态,但我无法通知另一个线程。
public synchronized void readTrap(Vector v)
{
Enumeration e = v.elements();
if(v.contains(PduTrap.UserLoginStatusTrap))
{
// gets status of login
status = loginUserManager.getStatus(e);
synchronized(syncObject)
{
// notify first method to read the new status
syncObject.notify();
}
}
}
status和SyncObject是我试图在线程之间共享的全局类型。我在类构造函数中将状态初始化为INPROGRESS。
private int status;
private Object syncObject;
有人可以告诉我为什么事情不起作用,或者我是否完全以错误的方式解决这个问题?目前,我的loginUser方法没有被readTrap通知。谢谢
答案 0 :(得分:0)
您可以考虑共享BlockingQueue
,以便readTrap(...)
方法add()
到队列(可能是新状态?)而loginUser(...)
会take()
从队列中。这样可以处理所有锁定和信令,而无需您进行等待/通知。
在调试代码方面,您需要确保syncObject
是private final
对象,以便等待和通知共享同一个对象引用 。显然,如果他们使用不同的对象,那么您的代码将无法正常工作。
此外,您应该在<{1}}块中设置内的状态。我不确定它在这里有所不同,但对代码至关重要的任何值都应该在互斥块中。您可以考虑在两种方法中打印status的值,以确保它像您想象的那样进行更新。
答案 1 :(得分:0)
这不是执行此类操作的唯一方法,但人们通常会将此类流程视为解决方案。 (我希望这不是那么抽象,以至于没有意义。)
- 方法1 -
它可以这样做,但通常比将其分成两组步骤的其他方式更难。
- 方法2 -
A部分
B部分
注意一个关键的区别是,第一种方式,你实际上有结果状态,你可以返回到调用这些东西的代码。第二种方式,这两个部分不再同步,你不能这样做。
您想要做什么取决于来电者的需求。
可能存在需要执行的SNMP命令列表。如果是这样,您只需要 B部分就可以在完成或标记失败时将其标记在列表中,以便其他人可以重试或通知某人。
也许对SNMP命令有一个排序,你必须按顺序执行一个,然后按顺序执行另一个。第一种方法适用于此,因为您可以按顺序拨打电话。第二种方法使得更难,因为 Part B 的异步完成必须查找然后启动序列中的下一项。这变得很复杂。
答案 2 :(得分:0)
请将您的syncObject对象作为final(私有Object syncObject = new Object(););请注意synchronized块使用Object引用;因此,如果对象引用发生更改,您将看不到所需的行为。
另外,请从这两个函数中删除synchronized,为什么需要它?如果两个线程都在同一个Object上工作;它可能会导致问题。请注意,synchronized方法使用此引用进行同步。