Java 当其他线程在映射上插入/删除时,迭代映射键

Java 当其他线程在映射上插入/删除时,迭代映射键,java,multithreading,Java,Multithreading,我有一个java多客户端服务器应用程序。服务器持续接收连接,每个客户端由单独的线程处理。客户端/服务器通信一直持续到套接字关闭。因此,从客户端接收的请求被放入LinkedBlockingQueue中,然后另一个线程处理该队列中的每个请求。由于客户机请求已添加到队列中,因此我将使用ConcurrentHashMap在稍后处理请求并准备响应时获取clientsocket,以便稍后将响应发送给客户机 现在,我需要实现一个超时功能,这样,如果请求没有被处理,并且响应在一段时间内没有准备好,那么就会向客户

我有一个java多客户端服务器应用程序。服务器持续接收连接,每个客户端由单独的线程处理。客户端/服务器通信一直持续到套接字关闭。因此,从客户端接收的请求被放入LinkedBlockingQueue中,然后另一个线程处理该队列中的每个请求。由于客户机请求已添加到队列中,因此我将使用ConcurrentHashMap在稍后处理请求并准备响应时获取clientsocket,以便稍后将响应发送给客户机

现在,我需要实现一个超时功能,这样,如果请求没有被处理,并且响应在一段时间内没有准备好,那么就会向客户端发送某种消息,说明您的请求现在无法处理。有谁能告诉我在多线程环境中做这件事的最佳方法吗。请记住,我有一个客户机映射,其中客户机连接针对每个请求id

我想有一个单独的线程,它将继续迭代映射键并检查时间。但是由于请求不断地添加到地图中,我想要一些最好的方法来完成它


谢谢使用并发哈希映射。它允许读取的完全并发性和写入的可调整并发性。它使用可变变量来放置数据。即使任何线程正在对某个存储桶进行任何修改,尝试从同一个存储桶读取数据的任何其他线程都可以看到该修改。

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 
        }
    }
};