我在java中有一个多客户端服务器应用程序。服务器继续接收连接,每个客户端由单独的线程处理。客户端/服务器通信继续,直到套接字关闭。因此,从客户端收到的请求放在LinkedBlockingQueue中,然后其他线程处理来自该队列的每个请求。由于客户端请求被添加到队列中,因此我在处理请求并准备好响应时使用ConcurrentHashMap来获取clientsocket,以便我可以稍后将响应发送给客户端。
现在我需要实现超时功能,因此如果请求不是进程并且响应在一段时间内没有准备好,那么会向客户端发送某种消息,表明您的请求现在无法处理。任何人都可以告诉我在多线程环境中做到这一点的最佳想法。请记住,我有一个客户端映射,其中客户端连接针对每个请求ID。
我正在考虑有一个单独的线程,它将继续迭代地图键并检查时间。但是由于请求继续在地图中添加,我想要一些最好的方法来做到这一点。
由于
答案 0 :(得分:2)
Guava的加载缓存可以解决您的超时和并发修改:https://code.google.com/p/guava-libraries/wiki/CachesExplained通过如下设置将请求映射交换到LoadingCache:
LoadingCache<Request, Connection> requests = CacheBuilder.newBuilder()
.maximumSize(1000)
.expireAfterAccess(1, TimeUnit.MINUTES)
.removalListener(MY_LISTENER)
.build(
new CacheLoader<Request, Connection>() {
public Connection load(Request request) throws AnyException {
return clientConnectionForRequest(request);
}
});
当请求进入时,您将其加载到缓存中:
requests.get(request);
在此之后,请求将在那里等待处理。如果开始处理,则获取连接并使请求无效,因此将其从缓存中删除。 ①
Connection c = requests.getIfPresent(request);
if (c != null) {
requests.invalidate(request); // remove from the waiting area
// proceeed with processing the request
} else {
// the request was evicted from the cache as it expired
}
在删除侦听器中,您需要实现一些侦听驱逐的简单逻辑。 (如果显式无效,则wasEvicted()
将返回false。)
MY_LISTENER = new RemovalListener<Request, Connection>() {
@Override
public void onRemovaRequest RemovalNotification<Request, Connection> notification) {
if (notification.wasEvicted()) {
Connection c = notification.getValue();
// send timeout response to client
}
}
};
您可以通过将请求放入队列并执行①中描述的方法来对请求进行排序。该方法还将仅处理那些没有超时的请求,您不需要额外的管家。
答案 1 :(得分:1)
使用并发哈希映射。它允许读取的完全并发和写入的可调整性。它使用volatile变量来放置数据。即使任何线程对存储桶进行了任何修改,任何其他尝试从同一存储桶读取数据的线程都可以看到它。