并发容器2

来源:互联网 发布:ifix组态软件编程入门 编辑:程序博客网 时间:2024/06/10 17:32

上篇博客通过HashMap的方式写了一个缓存的demo,这篇博客来改进一下这个Demo

 

用并发容器类ConcurrentHashMap来代替HashMap来改进上面的例子,因为ConcurrentHashMap是线程安全的,所以在访问底层Map时候就不需要进行同步了,因为避免了上篇博客中的阻塞问题。

 

代码如下:

 

public interface Computable<A,V>{V compute(A arg) throws InterruptedException;}public class ExpensiveFunction implements Computalbe<String ,BigInteger>{public BigInteger compute(String arg){return new BigInteger(arg);}}public class Memoizer2<A,V> implements Computable<A,V>{private final Map<A,V> cache=new ConcurrentHashMap<A,V>();private final Computable<A,V> c;public Memoizer2(Computable<A,V>,c){this.c=c;}public  V compute(A arg) throws InterruptedException{V result=cache.get(arg);if(result==null){result=c.compute(arg);cache.put(arg,result);}return result;}}


 

因为ConcurrentHashMap的线程安全性,所以Memorizer21要有更好的并发行为,但是其实这里面也还是有不足之处,当两个线程同时调用compute时候也是存在一个漏洞,可能会导致计算得到相同的值。

 

问题出现在与某个线程执行很长时间,其他线程并不知道这个线程正在执行,那么就可能会重复去计算。那么如何来解决这样的一个问题呢?

 

这时候就要用到FutureTask类了,FutureTask表示一个计算的过程,这个过程可能已经计算出结果,当然也可能正在执行。如果有结果那么FutureTask.get方法会立即返回结果,否则会一直阻塞,直到计算出结果再将其返回。

 

 

 

具体程序清单:

 

public interface Computable<A,V>{V compute(A arg) throws InterruptedException;}public class ExpensiveFunction implements Computalbe<String ,BigInteger>{public BigInteger compute(String arg){return new BigInteger(arg);}}public class Memoizer3<A,V> implements Computable<A,V>{private final Map<A,Future<V>> cache=new ConcurrentHashMap<A,Future<V>>();private final Computable<A,V> c;public Memoizer3(Computable<A,V>,c){this.c=c;}public  V compute(A arg) throws InterruptedException{Future<V> f=cache.get(arg);if(f==null){Callable<V> eval=new Callable<V>(){public V call() throws InterruptedException{return c.compute(arg);}};FutureTask<V> ft=new FutureTask<V>(eval);cache.put(arg,ft);ft.run();}try{return f.get();}catch(ExecutionException e){}}}


 

 

上面的程序看起来应该是完美的了,但是其实还是有一些瑕疵,下篇博客再来完善。

0 0
原创粉丝点击