2011-08-03 18 views
1

我們正在研究一個應用程序容器,它使用引用計數作爲跟蹤收到的請求和響應發送的機制。引用計數用於允許容器的正常關閉,即if (refCount == 0) shutdown;是引用計數好的設計

對於每個請求和對於未決響應,引用計數遞增。引用計數只在應用程序接受請求後遞減,並且也僅在應用程序發送了有效響應後才遞減。 所以,這裏是我的問題,在這種情況下,引用計數一個好的設計決定,比如說保留一個RequestContext,這個只在應用程序/容器發送響應時才關閉?

由於該軟件是在Java中實現的,我正在研究Java中的其他選項,並且遇到了這篇文章http://weblogs.java.net/blog/2006/05/04/understanding-weak-references,這使我認爲試圖利用ReferenceQueue可能是另一種做法。

+5

我想你在這裏超載的術語「引用計數」。如果將請求對象分配給新的引用,則不會增加引用計數,對吧?在這裏,我不認爲「參考」屬於術語。 –

回答

1

這實際上是一個非常乾淨的做法。您還應該另外使用ThreadLocal(如果您的請求 - 響應流水線將由單個線程處理)

基本上,當您收到請求時。使用WeakRefernce將ThreadLocal設置爲請求對象(或請求的某個屬性,例如用戶ID等)。然後你可以在你的處理流水線中的任何地方使用對象get()

如果您正在使用的工人線程池來處理請求,請確保您取消設置從你的線程的ThreadLocal弱引用對象,這樣存在的那個對象的更多引用。如果你爲每個請求產生一個新的線程,你甚至不需要這樣做。當線程死亡,對象會自動返回到的ReferenceQueue(因爲沒有活引用指向對象)

+0

「您還應該另外使用ThreadLocal(如果您的請求 - 響應管道將由單個線程處理)」。請澄清你的意思是容器是單線程的。如果是,那麼使用ThreadLocal實際上是浪費CPU週期。 – alphazero

+0

哦絕對不是..我在說一個多線程的容器..從我的措辭中赦免任何錯誤的暗示.. –

+0

感謝您的澄清。並請原諒我誤解你! – alphazero

1

請注意,您與性能命中那個櫃檯支付。實際上,對於您使用併發線程來處理請求的每個請求IFF,您都需要內存屏障。 (A內存屏障指令的成本通常高達200〜說明)。

根據您的問題,進一步看來你甚至不希望一個櫃檯,而是表示如果有任何活動的請求例如二進制標誌一個requestsInProgress標誌。這個想法是,當標誌值爲false時,你'正常關機'。

如果您的容器主要暴露網絡端點例如REST/HTTP然後我強烈建議你考慮NIO,並採用單線程調度機制來線性化容器外圍的req/rep。 (您可以在java.util.concurrent這些排隊和風扇出使用併發隊列的N個處理線程

[NIO subsystem] <-{poll}-[Selector(accept/read)/dispatch thread] => [Q:producer/consumer pattern 1:N] 
[NIO subystem] <-{poll}-[Selector(write)/responder thread] <= [Q:producer/consumer N:1] 

效益

如果您使用調度器和應答器則沒有記憶障礙所涉及的相同的話題 - ?的線程將固定到核心,並且您的標誌將獨佔其高速緩存行:

例如

調度隊列後要求: 增量req_in_progress

後,響應者出列響應: 遞減req_in_progress

有會看到是一個需要在關閉共享內存的同步,但是,這遠遠比這樣的開銷,更好每一個請求,因爲你只有當你真正需要它時付錢。

如果性能不是問題,那麼爲什麼不直接使用AtomicInteger作爲櫃檯並將其放到全球範圍內?