为什么我们需要缓存Java对象?有没有人能给我一个需要缓存对象的真实例子?另外,给出一些关于缓存设计、缓存类型以及多线程execution.What期间缓存的后果的一些观点。
既然内存中可以有普通的java对象,为什么我需要单独的缓存API。
发布于 2010-09-14 18:57:17
您不需要缓存对象,但是您可能希望这样做,以节省内存、I/O和CPU资源等。
内存
例如,JVM可能会缓存Integer对象,每当您请求创建一个新对象时,它可能只返回一个具有相同值的已存在对象的引用。阅读有关Flyweight模式的更多信息。
CPU
您可以通过在缓存中存储需要大量CPU计算的结果来节省CPU资源。相关技术:Memoization。
I/O
通过在应用程序中缓存一些数据,您可以节省I/O,而不必在每次访问时都访问数据库、硬盘或网络。
请求示例:
假设您正在构建一个需要显示股票行情的网站,您将通过web API (网络I/O)读取它们。您只需要每分钟更新一次价格(不频繁的更改)。你的网站同时被多个用户使用(并发/多线程)。
缓存解决方案可以是每分钟读取一次股票价格,然后将其保存在线程安全的对象中。每个线程(代表来自并发用户的请求)将从该对象读取数据,而不是每次(网络I/O节省)都访问web API。
该对象是线程安全的,因此在每分钟更新一次时,线程不会以不一致的状态读取该缓存值。
,所以每个客户端都需要等待其他客户端完成其任务?
Sidenote:这是一个并发问题,而不是缓存问题。
不,不一定,因为有在读取时不会阻塞的线程安全结构。此外,在本例中,只有一个线程将对对象进行(周期性的一分钟价格更新)。
更详细地说,假设我们将这些股票价格缓存到一个ConcurrentHashMap<String, BigDecimal>中,其中字符串表示股票代码,"GOOG","ORCL","MSFT“等,而BigDecimal表示股票的价格/报价。
为了服务于您的用户,您将像这样从该映射中读取值:
price = quotesMap.get("GOOG"); // get Google stocks quoteConcurrentHashMap.get()调用是线程安全的非阻塞(不需要锁定)调用,您的多个线程可以并发地从映射中进行检索。
所有的get()调用都将接收最新的完成的更新(由价格更新线程在调用ConcurrentHashMap.put()更新价格缓存时完成),这一事实确保了安全性。
发布于 2010-09-14 18:54:53
当创建对象的行为非常昂贵时,您希望缓存对象,这对于从磁盘读取数据而不是从ram读取数据,一直到高级编程语言,如Java,都是如此。如果创建一个对象需要10ms,从缓存中提取该对象需要1ms,如果您重用这些对象,您可以用10ms + 1ms创建对象并重用它,或者用10ms + 10ms创建对象两次。重用越多,缓存性能就越好。
当你写一个多线程程序时,你需要考虑对你的对象的并发访问,如果你有一个银行账户对象,两个线程读取余额并更新它,你可以结束两个线程读取相同的值,并在此基础上写入一个新值,所以两个as 100的存款可能导致您的银行余额仅增加as 100,因为第二个要更新的线程具有一个陈旧的当前余额值。
除了synchronized关键字之外,java.util.concurrent包中还有许多类用于处理并发性。这里有很多来自Oracle here的资源。
https://stackoverflow.com/questions/3708117
复制相似问题