技术开发 频道

剖析Jive的缓存机制


IT168技术文档】 
   
forum.jsp <% // ResultFilter结果过滤类 ResultFilter filter = new ResultFilter(); filter.setStartIndex(start); filter.setNumResults(range); //调用Dbforum的threads()方法,获得ForumThreadIterator对象实例 ForumThreadIterator threads = forum.threads(filter); ...... while (threads.hasNext()) { //对thead进行遍历 ForumThread thread = (ForumThread)threads.next(); //得到thread的ID long threadID = thread.getID(); //得到线索的根帖子rootMessage ForumMessage rootMessage = thread.getRootMessage(); //得到帖子主题和作者等信息 String subject = rootMessage.getSubject(); User author = rootMessage.getUser(); ...... } %> DbForum.java public class DbForum implements Forum, Cacheable { ...... public ForumThreadIterator threads(ResultFilter resultFilter) { //生成SQL语句 String query = getThreadListSQL(resultFilter, false); //得到threadID块 long [] threadBlock = getThreadBlock(query.toString(), resultFilter.getStartIndex()); ...... //返回ForumThreadBlockIterator对象 return new ForumThreadBlockIterator(threadBlock, query.toString(), startIndex, endIndex, this.id, factory); } protected long[] getThreadBlock(String query, int startIndex) { int blockID = startIndex / THREAD_BLOCK_SIZE; int blockStart = blockID * THREAD_BLOCK_SIZE; String key = query + blockID; //根据Key的值到缓存中取得ThreadID的数组 CacheableLongArray longArray =(CacheableLongArray)threadListCache.get(key); //在缓存中则返回 if (longArray != null) { long [] threads = longArray.getLongArray(); return threads; } // 否则到数据库中取ThreadID的块,以数组形式返回 else { LongList threadsList = new LongList(THREAD_BLOCK_SIZE); Connection con = null; Statement stmt = null; ...数据库操作 ... } long [] threads = threadsList.toArray(); //将 ThreadID的块加入缓存 threadListCache.add(key, new CacheableLongArray(threads)); return threads; } ...... }
    在forum.jsp中有一个ResultFilter类的实例resultFilter。它给出页面显示Thread的起始位置和数量,并作为参数传入forum.threads()中,用于构造相关的SQL语句。当调用forum.threads(filter)时,程序将生成的SQL语句传入到getThreadBlock()方法中得到一个threadID的块,也就是一组threadID。之所以要读threadID块,是因为显示论坛时并不是显示一条线索就行了,而是一下显示十几条。这样做可以避免反复读数据库,而且threadID不是thread对象,并不占太大空间。

 应该说使用了块以后,减轻了数据库的访问量,因而论坛的效率有了很大的提高。不仅如此,Jive又把块放入了缓存中。在getThreadBlock()方法里,Jive用Cache类的实例对象threadListCache来缓存threadID块,而关键字就是SQL语句加上blockID。也就是说,只要SQL语句和blockID相同,就可以在缓存中取出相同的threadID块。当然,缓存中找不到,还是要到数据库中读出来加入缓存的,这样论坛的效率又得到了进一步的提升。

 ForumThreadBlockIterator类继承自ForumThreadIterator抽象类,而ForumThreadIterator类又实现了Iterator接口,因此得到ForumThreadBlockIterator的实例对象threads后,就可以在用threads.next()方法对它进行编历了。ForumThreadBlockIterator类的功能就是逐个读取ThreadID,然后根据ThreadID返回Thread对象,由此上层访问接口就和中间层衔接起来了。

 小结

 Jive的缓存机制值得学习的地方有很多,比如读取线索时不是读一条而是读一个block;显示线索的起始位置和数量用专门的一个类来管理,并且动态生成SQL语句;用一个专门的类来负责管理缓存;把论坛缓存对象的功能抽象出来形成一个缓存的抽象类DatabaseCache,让它去跟低层数据结构联系起来等。这些都体现了面向对象的设计原则,即提高软件的可维护性和可复用性。

 同时,Jive也告诉我们,要想编好程序,只懂条件语句和循环语句可不行,还要必须选择好的数据结构,掌握好的面向对象的设计原则,熟悉设计模式思想方法,这样才能编写出强壮、高效的代码。
0
相关文章