簡體   English   中英

如何最好地同步訪問Java中一個類的兩個線程

[英]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() 這無需您等待/通知即可處理所有鎖定和發信號。

在調試代碼方面,您需要確保syncObjectprivate final對象,以便wait和notify共享相同的對象引用 顯然,如果它們在不同的對象上工作,則您的代碼將無法工作。

另外,您應該在synchronized設置狀態。 我不確定這里是否有區別,但是任何對代碼至關重要的值都應位於互斥鎖塊中。 您可能會考慮同時使用兩種方法打印狀態值,以確保按您的想法進行更新。

這不是執行此類操作的唯一方法,但是人們通常將這種流程視為解決方案。 (我希望這不是那么抽象,以至於沒有意義。)

-方法1--

  1. 做某事
  2. 發信號通知其他事情以異步方式完成一些工作
  3. 在結果出現之前什么都不做
  4. 完成您的開始
  5. 將完成狀態返回到其他代碼。

可以通過這種方式完成,但是通常比將其分為兩組步驟的另一種方式要困難得多。

-方法2--

甲部

  1. 做某事
  2. 節省進行中的工作
  3. 發信號通知其他事情以異步方式完成一些工作
  4. 忘掉它

B部分

  1. 得到通知,另一件事已經完成。
  2. 檢索正在進行的工作
  3. 做剩下的工作
  4. 全部做完

注意一個關鍵的區別是,第一種方式,您實際上具有結果狀態,您可以返回調用該程序的代碼。 第二種方式,這兩個部分不再同步,您將無法做到這一點。

您要做什么取決於呼叫者的需求。

也許有一列需要執行的SNMP命令。 如果是這樣,那么您需要的是B部分在完成時將其標記在列表之外或標記為失敗,以便其他人可以重試或通知某些人員。

可能對SNMP命令有一個命令,您必須先執行一個命令,然后再執行另一個命令。 第一種方法對此效果很好,因為您可以按順序放置調用。 第二種方法使這一點變得更加困難,因為B部分的異步完成將不得不查找然后啟動序列中的下一項。 這變得很復雜。

請使您的syncObject對象成為最終對象(私有對象syncObject = new Object();); 請注意,同步塊使用對象引用; 因此,如果對象引用發生更改,您將看不到所需的行為。

另外,請同時從兩個功能中刪除同步功能,為什么需要它? 如果兩個線程都在同一個對象上工作; 它可能會引起問題。 請注意,同步方法使用此參考進行同步。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM