2011-08-09 103 views
0

我有一個應用程序(服務器端)位於一個端口,並偵聽客戶端連接。 建立連接後,應用程序將啓動處理該連接的解析器(另一個線程)。阻止共享數據的Java線程?

我的問題是,在某些點(因爲解析可能需要很長時間)服務器應用程序啓動一個新的線程,而其他正在處理。這是一種理想的行爲,而不是本身的問題。會發生什麼情況是新線程似乎從舊線程讀取了一些狀態變量,因此行爲錯誤。

鬆散地說,解析器所做的是: 客戶端總是發送兩個數據包;第一個基本上是一個爆震包,第二個是真正的數據包。 我讀了第一個,如果我決定接受它,我把它放在一個變量中,以便下一個數據包可以被讀取。

在描述的場景中,第一個線程讀取爆震數據包並驗證它。 下一個數據包到達(在同一個線程上)並開始解析。

同時,創建另一個分析器並等待它的第一個數據包; 然後會發生什麼(問題)是它檢查驗證變量(對於此線程應該爲false)並且它發現它是正常的(它從仍在執行的前一個線程中讀取)並繼續解析如同它是數據包一樣敲敲包。

什麼是lokoing是一種完全消除數據共享的方法。我正在使用以下課程來跟蹤會話狀態:

public class SessionInfo { 

    private Constants.PacketValidity validity; 
    private int packetSize; 
    private String IMEI; 
    private int packetReportedSize; 
    private Constants.PacketType packetType; 
    private int codec; 
    private int records; 
    private boolean valid; 
    private Constants.ResponseType responseType; 
    private String clientIP; 
    private int serverPort; 
    private Date parseInit; 
    private Date parseEnd; 
} 

除此之外,該類有一堆setter和getter。

解析器將此對象的一個​​實例作爲專用字段。

我會如何實現這一目標?

+0

圍繞創建線程和檢查變量來展示您的代碼。 – DaveJohnston

+0

兩個數據包對應在同一個會話上嗎?如果他們在同一個會話中,他們應該可以構建類似對話的東西,即SessionInfo更像ConversationInfo,並且應該有多個實例。 – tkr

回答

2

解析器將此對象的一個​​實例作爲專用字段。

這是你的問題。解決方案是創建一個新的SessionInfo並將其作爲方法參數傳遞給解析器,並將其傳遞給進一步的方法調用。一旦你這樣做了,對會話狀態的引用就會成爲當前線程執行的本地對象。

如果解析器包含更多在解析過程中更新的私有屬性,則還需要解壓縮這些屬性。將它們組合到一個私有子類中,並在調用解析時創建該類的一個實例將是解決該問題的可能方案。

2

您需要確保兩個單獨的線程使用兩個單獨的SessionInfo實例。

最簡單的方法是創建一個新的解析器實例,然後創建一個新的實例SessionInfo。一旦你確定他們有單獨的實例,你應該沒問題。