Java 如何同步缓存列表访问

Java 如何同步缓存列表访问,java,multithreading,caching,synchronization,locking,Java,Multithreading,Caching,Synchronization,Locking,我遇到了以下问题(一个重要的限制-不能使用外部jar/库,只能使用常规安装附带的java原语): 类X的对象长期存储在sql DB中。缓存对象是为了性能(需要写入。打算基于LinkedHashMap) get(key): 检查对象是否在缓存中且未使用-返回它。 如果对象正在使用中-睡眠直到可用。 如果对象不在缓存中,则从数据库中读取它 putInCache(对象): 更新缓存中的对象(如果不存在,则添加它)。 如果缓存耗尽,它将触发缓存的saveToDB操作并删除 从缓存中选择最近使用最少的项

我遇到了以下问题(一个重要的限制-不能使用外部jar/库,只能使用常规安装附带的java原语):

类X的对象长期存储在sql DB中。缓存对象是为了性能(需要写入。打算基于LinkedHashMap)

get(key)
: 检查对象是否在缓存中且未使用-返回它。 如果对象正在使用中-睡眠直到可用。 如果对象不在缓存中,则从数据库中读取它

putInCache(对象)
: 更新缓存中的对象(如果不存在,则添加它)。 如果缓存耗尽,它将触发缓存的
saveToDB
操作并删除 从缓存中选择最近使用最少的项

saveToDB(对象)
: 将对象写入数据库(未从缓存中删除),并标记对象和“未更改”

有多个线程调用
get
。线程可以更改它从
get
接收到的对象(该对象将被标记为“已更改”)—完成后,它将调用
putInCache

在缓存对象上有一个专用线程,当它遇到一个“已更改”的对象时,它将触发
saveToDB
(对象将在数据库访问进行时标记为已使用)

您建议如何确保线程安全? 基本上,我正在寻找合适的Java类来支持: 1. <代码>获取以同步其对缓存中每个对象的访问。这样它就可以检查它是否在那里,如果在那里,它是否被使用或免费抓取。如果它被使用-它应该一直休眠到可用为止。 2.调用
saveToDB
时,专用线程不应锁定缓存,但仍应确保检查了所有缓存,并且没有导致饥饿(在运行
saveToDB
时,缓存可能会更改)

我只是想澄清一下,我只对锁定/同步解决方案感兴趣-缓存触发和数据库访问等问题可以假定为给定的。

以下是一种方法:

  • 使用执行器服务处理数据库请求
  • 使用
    Future
    s作为地图值
  • 使用
    ConcurrentHashMap
    作为映射实现
未来的
应该从数据库获取;它将使用执行器服务

当您需要对一个对象进行操作时,请在此将来的
.get()
对象上进行同步


此外,谷歌还推出了“实践中的Java并发”,并购买了这本书;)

我将首先使用
synchronized
,您似乎不需要持有此锁来执行saveToDB。当你想要的钥匙正在使用时,你可以使用锁来
wait()
。@PeterLawrey:请你详细说明一下好吗?您的意思是用synchronize包装所有函数吗?它将如何解决我的问题?我是java新手,所以我可能缺少一些基本的和明显的东西……当您使用synchronized包装所有方法时,它们都隐式地共享一个锁,因此一次只能由一个线程访问缓存。这意味着如果你可以避免包装任何可能是个好主意的方法,特别是如果这些方法中的任何一个访问网络或任何东西非常慢的话稍后您可以了解更复杂的锁定/线程安全策略,但我会首先掌握使用synchronized。我不想使用它——特别是在“专用线程”中,因为将所有更改的对象保存到DB需要一些时间。这就是为什么我在寻找一种更适合自己的方法。也许是这样,但至少它是有效的(tm)。首先让您的代码使用它,然后使用更细粒度的锁定。谢谢您的建议。我会去读你提到的课程。我确实有一本书,我在发布时正在读(“JVM上的并发编程”)。注意:当我指的是
Future
时,我的意思是
FutureTask
。它实现了
Future
Callable