![](/img/trans.png)
[英]How can I synchronize two threads in Java by extending the Thread class?
[英]How to best synchronize two threads accessing one class in Java
我有一個發送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;
有人可以告訴我為什么事情不起作用,還是我完全以錯誤的方式去做? 當前,readTrap尚未通知我的loginUser方法。 謝謝
您可能會考慮使用共享的BlockingQueue
因此readTrap(...)
方法會將add()
到隊列中(也許是新狀態?),而loginUser(...)
將從隊列中take()
。 這無需您等待/通知即可處理所有鎖定和發信號。
在調試代碼方面,您需要確保syncObject
是private final
對象,以便wait和notify共享相同的對象引用 。 顯然,如果它們在不同的對象上工作,則您的代碼將無法工作。
另外,您應該在synchronized
塊內設置狀態。 我不確定這里是否有區別,但是任何對代碼至關重要的值都應位於互斥鎖塊中。 您可能會考慮同時使用兩種方法打印狀態值,以確保按您的想法進行更新。
這不是執行此類操作的唯一方法,但是人們通常將這種流程視為解決方案。 (我希望這不是那么抽象,以至於沒有意義。)
-方法1--
可以通過這種方式完成,但是通常比將其分為兩組步驟的另一種方式要困難得多。
-方法2--
甲部
B部分
注意一個關鍵的區別是,第一種方式,您實際上具有結果狀態,您可以返回調用該程序的代碼。 第二種方式,這兩個部分不再同步,您將無法做到這一點。
您要做什么取決於呼叫者的需求。
也許有一列需要執行的SNMP命令。 如果是這樣,那么您需要的是B部分在完成時將其標記在列表之外或標記為失敗,以便其他人可以重試或通知某些人員。
可能對SNMP命令有一個命令,您必須先執行一個命令,然后再執行另一個命令。 第一種方法對此效果很好,因為您可以按順序放置調用。 第二種方法使這一點變得更加困難,因為B部分的異步完成將不得不查找然后啟動序列中的下一項。 這變得很復雜。
請使您的syncObject對象成為最終對象(私有對象syncObject = new Object();); 請注意,同步塊使用對象引用; 因此,如果對象引用發生更改,您將看不到所需的行為。
另外,請同時從兩個功能中刪除同步功能,為什么需要它? 如果兩個線程都在同一個對象上工作; 它可能會引起問題。 請注意,同步方法使用此參考進行同步。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.