具有过期可能性的简单 Java 字符串缓存
我正在为 Java 1.5 应用程序寻找具有过期功能的并发集。它将用作存储/缓存在一定时间后过期的名称(即字符串值)的简单方法。
我试图解决的问题是两个线程不应该能够在一定时间内使用相同的名称值(所以这是一种黑名单,确保相同的“名称”,就像消息引用一样,可以在经过一定时间段之前不会被另一个线程重用)。我自己不控制名称生成,因此我无法对实际名称/字符串执行唯一性,它应该被视为一种节流/限制机制,以防止同一名称每秒使用多次。
例子: 线程 #1 执行 cache.add("unique_string, 1)
操作,将名称“unique_string”存储 1 秒。 如果任何线程在 1 秒内通过执行例如 cache.get("unique_string")
来查找“unique_string”,它将获得肯定响应(项目存在),但此后该项目应该过期并且从集合中删除。
该容器有时每秒处理 50-100 次插入/读取。
我确实一直在寻找不同的解决方案,但没有找到任何我认为真正适合我的需求的解决方案。这感觉像是一个简单的问题,但我发现的所有解决方案都太复杂或太过分了。
一个简单的想法是有一个 ConcurrentHashMap 对象,其键设置为“name”,值设置为过期时间,然后每秒运行一个线程并删除其值(过期时间)已过的所有元素,但是我不确定这会有多有效?我缺少一个更简单的解决方案吗?
I am looking for a concurrent Set with expiration functionality for a Java 1.5 application. It would be used as a simple way to store / cache names (i.e. String values) that expire after a certain time.
The problem I'm trying to solve is that two threads should not be able to use the same name value within a certain time (so this is sort of a blacklist ensuring the same "name", which is something like a message reference, can't be reused by another thread until a certain time period has passed). I do not control name generation myself, so there's nothing I can do about the actual names / strings to enforce uniqueness, it should rather be seen as a throttling / limiting mechanism to prevent the same name to be used more than once per second.
Example:
Thread #1 does cache.add("unique_string, 1)
which stores the name "unique_string" for 1 second.
If any thread is looking for "unique_string" by doing e.g. cache.get("unique_string")
within 1 second it will get a positive response (item exists), but after that the item should be expired and removed from the set.
The container would at times handle 50-100 inserts / reads per second.
I have really been looking around at different solutions but am not finding anything that I feel really suites my needs. It feels like an easy problem, but all solutions I find are way too complex or overkill.
A simple idea would be to have a ConcurrentHashMap
object with key set to "name" and value to the expiration time then a thread running every second and removing all elements whose value (expiration time) has passed, but I'm not sure how efficient that would be? Is there not a simpler solution I'm missing?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
Google 的 Guava 库包含这样的缓存: CacheBuilder。
Google's Guava library contains exactly such cache: CacheBuilder.
如何使用线程执行器创建一个项目过期的 Map
然后您可以使用一种方法将缓存名称添加到您的集合中,该方法将在它过期后将其删除,在本例中为一秒钟。我知道这看起来像是相当多的代码,但只需几个方法就可以成为一个非常优雅的解决方案。
How about creating a Map where the item expires using a thread executor
You can then have a method that adds the cache name to your collection which will remove it after it has expired, in this example its one second. I know it seems like quite a bit of code but it can be quite an elegant solution in just a couple of methods.
一个简单的、独特的字符串模式,不会重复
即使您重新启动应用程序,也不会重复。
注意:它将在以下情况下重复:
A simple unique string pattern which doesn't repeat
This won't repeat even if you restart your application.
Note: It will repeat after:
这取决于 - 如果您需要严格的时间条件,还是软的(如 1 秒 +/- 20 毫秒)。
另外,如果您需要离散缓存失效或“通过调用”。
对于严格的条件,我建议添加一个不同的线程,该线程每 20 毫秒就会使缓存失效。
您还可以查看存储的密钥时间戳并检查它是否已过期。
It depends - If you need strict condition of time, or soft (like 1 sec +/- 20ms).
Also if you need discrete cache invalidation or 'by-call'.
For strict conditions I would suggest to add a distinct thread which will invalidate cache each 20milliseconds.
Also you can have inside the stored key timestamp and check if it's expired or not.
为什么不将密钥列入黑名单的时间存储在地图中(如
像这样的东西:
Why not store the time for which the key is blacklisted in the map (as Konoplianko hinted)?
Something like this: