2011-08-03 20 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作为柜台并将其放到全球范围内?