如何知道在JAVA中没有操作在ConcurrentHashMap上运行或处于空闲状态?

如何知道在JAVA中没有操作在ConcurrentHashMap上运行或处于空闲状态?,java,multithreading,concurrenthashmap,Java,Multithreading,Concurrenthashmap,我的情况是,每当我的ConcurrentHashMap更新时,我都需要清除一个现有文件,并将整个数据再次写入该文件。因此,每次更新时,清除文件并将数据再次写入文件会导致高延迟。所以我认为每当我的hashmap处于空闲状态时,比如如果没有更新操作,那么我将把整个数据写入文件,否则我将等待hashmap空闲 基本上,我将从映射中不断删除字符串。所以每次我从HashMap中删除一个字符串写入文件都是一个非常昂贵的操作。那么,有没有办法知道ConcurrentHashMap上没有删除操作?听起来您需要利

我的情况是,每当我的ConcurrentHashMap更新时,我都需要清除一个现有文件,并将整个数据再次写入该文件。因此,每次更新时,清除文件并将数据再次写入文件会导致高延迟。所以我认为每当我的hashmap处于空闲状态时,比如如果没有更新操作,那么我将把整个数据写入文件,否则我将等待hashmap空闲


基本上,我将从映射中不断删除字符串。所以每次我从HashMap中删除一个字符串写入文件都是一个非常昂贵的操作。那么,有没有办法知道ConcurrentHashMap上没有删除操作?

听起来您需要利用封装,将ConcurrentHashMap包装在一个类中,并且可能有带有队列的add/remove方法。查看包中的其他选项

这个想法是使用队列。对映射的每次访问都将通过从包装器中调用add/remove并将其添加到队列中进行。然后将有一个无限线程循环占用队列。执行此操作时,您可以检查队列是否为空,并执行文件持久化

那么有没有办法知道ConcurrentHashMap上没有删除操作

简短回答:没有办法

但即使没有,你也会遇到麻烦。例如,假设新的更新在您开始清除/写入后立即到达

我认为解决方案是使用两个映射和一个队列

发生更新请求时: 在并发hashmap上执行更新 将请求添加到队列中 在后台线程中: 从队列中提取请求,并对第二个shadowhashmap执行更新 定期或基于其他一些条件,停止拉取请求,并将shadowhashmap刷新到文件中。 主hashmap总是快速更新,并且总是最新的。更新和使用主hashmap的操作不会被显著阻止

在写入卷影哈希映射时,队列提供请求缓冲

第二个hashmap只由一个线程访问,因此它不需要是并发的。因此它会更快

文件的状态通常会稍微落后于主hashmap。但这是不可避免的。避免这种情况的唯一方法是阻止对主地图的更新。。。这就是你想要避免的


另一种方法是加快文件写入速度。我怀疑它之所以慢是因为您当前的设计要求您每次都清除并重写文件。另一种方法是只将更改写入文件。这意味着您在重新启动时可能有更多的工作要做。。。假设文件的目的是记录映射状态,以便您可以重新启动。

您可以使用一个简单的共享标志,在删除操作开始之前将其设置为true,在删除操作之后将其设置为false,并在其他线程中不断检查此标志的值,只要您发现共享标志为false,进入文件操作。检查队列是否为空,并执行文件持久化。这可能是一个等待发生的TOCTOU错误——如果队列从未被发现为空,会发生什么?哈希映射永远不会保存到磁盘。我怀疑简单地将哈希映射序列化到文件是写入它的最快方式。最好将地图保存到一个新文件中,然后将新文件重命名为旧文件。这样,磁盘上总是有一个有效的副本。这取决于文件的大小和更改的速率。将有一个收支平衡点,即存储增量比存储快照快。考虑到好的SSD可以用不到100美元的价格买到,这个收支平衡点将是一个非常巨大的文件。与尝试编写代码相比,用更快的硬件将此映射保存到磁盘,可以更便宜、更快地解决任何性能问题,而且更不容易出现错误。没有那么大。序列化和持久化映射会消耗CPU时间和物理I/O时间。事实上,如果您在Linux系统上重复写入/重写同一文件,那么性能可能不受磁盘输出速度的限制。当字节写入磁盘或SSD时,操作系统不会挂起应用程序。它以异步方式向设备写入数据。即使OP不是一名高价员工,编写增量存储解决方案的人工成本可能至少要几千美元,还有bug和O&M尾巴需要支付。这是很多快速的硬件。