用java容器实现缓存

有这么个问题:
应用程序定时的读取数据库,并将数据写入缓存.
为避免用户读缓存时,程序更新缓存,使用户读到错误数据,使用了java的同步容器Hashtable和Vector实现.
根据数据库字段值的不同,将数据分别放到几个不同的Vector.
类似这样
[code="java"]Vector v1 = new Vector();
..
for(数据){
if (数据i.属性 == "name")
v1.add(数据i)
}
..
static h.add("name",v1);[/code]
..
像这样的代码没什么扩展性,而且很依赖数据库数据.但是它有个好处,就是线程安全.用户读到的数据都是有效的.

如果根据数据库数据动态生成Vector,像这样
[code="java"]for(数据){
Vector v = null;
if(hash.containsKey(属性)){
v = hash.get(属性)
v.add(数据i)
}else{
v = new Vector();
v.add(数据i);
hash.add(v);
}
}[/code]
也有问题,就是Vector里新写入的对象会和原来的重复.

如果先清理缓存hash.clear();则可能此时用户正在读数据,结果读不到任何数据.或者任何时候在Vector写入新数据都要删除原数据,正样都有可能使用户读不到数据..

有什么办法,即可以让用户读到有效数据,又能保留程序灵活性
[b]问题补充:[/b]
不知道我的描述是否清楚,

业务需求是在更新数据的时候进行同步控制,
用new Vector这种方式,相当于vector.add(数据)的时候,用户依然可以读之前存在hashtable中的数据,只是最后在hash.add(Vector)的时候才进行同步,这个时间是很短的,因为只有几个Vector(Vector里面的数据会很多)被加入到hashtable.

如果不考虑容器,而是手动在更新缓存的前后加锁,解锁,那么这个时间会比较长,可能达不到上一种实现的性能.

用Concurrent包,能达到甚至超过上一种实现的性能吗.
[b]问题补充:[/b]
concurrent是不错,可惜解决不了我的问题.
测试了一下,
hashtable.add("",vector)只有几个vector,在毫秒级别上耗时为0.
用concurrent把更新缓存的过程锁定,其间循环一万条数据并添加到ArrayList,然后添加到hashmap,耗时约16毫秒,还是很有差距...
[b]问题补充:[/b]
你们的答案都类似,分数只能给一个人。

Concurrent不太了解,我的问题是要求锁定的时间尽可能短,即便concurrent有同步的list,我还是要清空list,然后把新数据写入,list要装的数据量是很大的,这样可能会让用户等待时间比较长.

我现在的做法,是把数据写入新的list,这过程不需要同步,最后把list写入hashtable,这个过程需同步,可list数量很少,所以这个过程时间很短。代价就是牺牲了一些可维护性和扩展性。

4个回答

这个问题很简单, 首先, 你操作数据库的时候, 

Vector/Hashtable 你不要用了, 用Concurrent包

如果说, 你需要整个替换数据, 那么我建议你, 把数据库读入的时候, 放在一个新的Vector/Hashtable.然后, lock 老的 Vector/Hashtable 对象, 把新的对象 [b]assgin[/b]过去. 这样, 你就不需要使用同步了。

不过, 我建议你使用Concurrent包。 直接把新数据写进去.

原始的做法是:

将你的同步Hashtable和Vector变会普通的集合。
然后:
[code="java"]

public final static Object lock = new Object();

//...修改用户数据
synchronized(lock){

//do something ..

map.clear();

//do something ..

}

//...读取用户数据
User user = null;
synchronized(lock){

//do something ..

user = map.get(...);

//do something ..

}

//do something ..

[/code]

当然,以上是jdk1.4或以前的原始做法.

jdk1.5以后还是推荐用java.util.concurrent.locks.ReentrantReadWriteLock

[quote="shaka"]如果不考虑容器,而是手动在更新缓存的前后加锁,解锁,那么这个时间会比较长,可能达不到上一种实现的性能.

用Concurrent包,能达到甚至超过上一种实现的性能吗. [/quote]

性能上,concurrent比synchronized要优

concurrent 不是然你用LOCK对象, 你找找concurrent的list/hashmap 类似的API。 另外, 你的时间计算不准确的。 我相信你在WINDOWS上干活的吧, WINDOWS的时间精度很烂的。 你的测试, 要考虑热启动的因素。JAVA的数据结构没有任何的性能因素。我觉得你应该了解下如何做程序片段的性能测试。

Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!