1

我们正在开发一个应用程序容器,它使用引用计数作为跟踪接收到的请求和发送的响应的机制。引用计数用于允许容器正常关闭,即if (refCount == 0) shutdown;

对于每个请求以及待处理的响应,引用计数都会增加。仅当应用程序接受请求并且仅当应用程序发送有效响应时,引用计数才会减少。所以这是我的问题,在这种情况下引用计数是否是一个好的设计决策,比如与RequestContext仅在应用程序/容器发送响应时保持关闭的情况相比?

由于该软件是用 Java 实现的,因此我正在查看 Java 中的其他选项并遇到了这篇文章http://weblogs.java.net/blog/2006/05/04/understanding-weak-references这让我觉得尝试利用ReferenceQueue可能是另一种方法来做到这一点。

4

2 回答 2

1

这实际上是一种非常巧妙的方法。您还应该另外使用ThreadLocal(如果您的请求 - 响应管道将由单个线程处理)

基本上,当您收到请求时。将带有 WeakReference 的 ThreadLocal 设置为您的请求对象(或请求的某些属性,例如用户 ID 等)。然后,您可以get()在处理管道中的任何位置创建对象。

如果您使用工作线程池来处理请求,请确保从线程的 ThreadLocal 中取消设置弱引用对象,以便不再存在该对象的引用。如果您为每个请求生成一个新线程,您甚至不需要这样做。当线程终止时,对象将自动返回到referenceQueue(因为没有实时引用指向该对象)

于 2011-08-03T21:05:16.017 回答
1

请注意,您将为该计数器支付性能命中的费用。实际上,如果您使用并发线程为请求提供服务,则您需要为每个请求 IFF 设置内存屏障。(一条内存屏障指令通常需要多达 200 条指令。)

根据您的问题,您似乎甚至不需要计数器,而是需要一个二进制标志来指示是否有任何活动请求,例如requestsInProgress标志。当标志值为false.

如果您的容器主要暴露网络端点,例如 REST/HTTP,那么我强烈建议您考虑 NIO 并采用单线程调度机制来线性化容器外围的 req/rep。(您可以使用java.util.concurrent.

[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计数器并将其放在全局上下文中呢?

于 2011-08-03T21:58:27.813 回答