Java 当其他线程在映射上插入/删除时,迭代映射键
我有一个java多客户端服务器应用程序。服务器持续接收连接,每个客户端由单独的线程处理。客户端/服务器通信一直持续到套接字关闭。因此,从客户端接收的请求被放入LinkedBlockingQueue中,然后另一个线程处理该队列中的每个请求。由于客户机请求已添加到队列中,因此我将使用ConcurrentHashMap在稍后处理请求并准备响应时获取clientsocket,以便稍后将响应发送给客户机 现在,我需要实现一个超时功能,这样,如果请求没有被处理,并且响应在一段时间内没有准备好,那么就会向客户端发送某种消息,说明您的请求现在无法处理。有谁能告诉我在多线程环境中做这件事的最佳方法吗。请记住,我有一个客户机映射,其中客户机连接针对每个请求id 我想有一个单独的线程,它将继续迭代映射键并检查时间。但是由于请求不断地添加到地图中,我想要一些最好的方法来完成它Java 当其他线程在映射上插入/删除时,迭代映射键,java,multithreading,Java,Multithreading,我有一个java多客户端服务器应用程序。服务器持续接收连接,每个客户端由单独的线程处理。客户端/服务器通信一直持续到套接字关闭。因此,从客户端接收的请求被放入LinkedBlockingQueue中,然后另一个线程处理该队列中的每个请求。由于客户机请求已添加到队列中,因此我将使用ConcurrentHashMap在稍后处理请求并准备响应时获取clientsocket,以便稍后将响应发送给客户机 现在,我需要实现一个超时功能,这样,如果请求没有被处理,并且响应在一段时间内没有准备好,那么就会向客户
谢谢使用并发哈希映射。它允许读取的完全并发性和写入的可调整并发性。它使用可变变量来放置数据。即使任何线程正在对某个存储桶进行任何修改,尝试从同一个存储桶读取数据的任何其他线程都可以看到该修改。Guava的加载缓存可以为您解决超时和并发修改问题:通过如下设置将您的请求映射交换到加载缓存:
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);
}
});
在此之后,请求将在那里等待处理。如果处理已启动,则获取连接并使请求无效,以便将其从缓存中删除。①
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
}
在删除侦听器中,您需要实现一些简单的逻辑来侦听逐出。(如果显式无效,则wasvecuted()
将返回false。)
MY_LISTENER=new RemovalListener(){
@凌驾
公共无效OnRemovareRequest RemovalNotification(通知){
if(notification.wasvecuted()){
连接c=notification.getValue();
//向客户端发送超时响应
}
}
};
您可以通过将请求放置在队列中并执行中描述的方法来排序请求① 该方法还将只执行那些尚未超时的请求,您不需要额外的内部管理。此答案可能有助于@VigneshVino终止线程池对于解决当前问题没有多大意义。以这种方式正确实现超时很困难。有一些库可以为您实现此功能。
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
}
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
}
}
};