在Java并发实践中由Brian Goetz [英] In Java Concurrency In Practice by Brian Goetz

查看:110
本文介绍了在Java并发实践中由Brian Goetz的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Java并发在实践中,Brian Goetz提供了一个高效的可扩展缓存,用于并发使用。下面是类的代码:

Java Concurrency In Practice by Brian Goetz provides an example of a efficient scalable cache for concurrent use. Here is the code for the class:

public class Memoizer<A, V> implements Computable<A, V> {
    private final ConcurrentMap<A, Future<V>> cache
        = new ConcurrentHashMap<A, Future<V>>();
    private final Computable<A, V> c;

    public Memoizer(Computable<A, V> c) { this.c = c; }

    public V compute(final A arg) throws InterruptedException {
        while (true) {
            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);
                f = cache.putIfAbsent(arg, ft);
                if (f == null) { f = ft; ft.run(); }
            }
            try {
                return f.get();
            } catch (CancellationException e) {
                cache.remove(arg, f);
            } catch (ExecutionException e) {
                throw launderThrowable(e.getCause());
            }
        }
    } }

可能是一个愚蠢的问题, coudl任何人都告诉我这个类的并发使用?
像一个主要的?

Probably a stupid question but coudl anyone show me the concurrent usage of this class? Like in a main?

干杯,
Agata

Cheers, Agata

推荐答案

下面是一个计算阶乘的例子:

Here is an example which calculates factorials:

public static void main(String[] args) throws Exception {

    //create a memoizer that performs factorials
    final Memoizer<Integer, Integer> memo = new Memoizer<Integer, Integer> (new Computable<Integer, Integer>() {
        @Override
        public Integer compute(Integer a) {
            int result = 1 ;
            for(int i = 1 ; i < a ; i++){
                result = result*i;
            }
            return result;
        }
    });

    //now call the memoizer
    System.out.println(memo.compute(10));


    //call it with 10 threads concurrently
    ExecutorService exec = Executors.newFixedThreadPool(10);
    ExecutorCompletionService<Integer> compService = new ExecutorCompletionService<Integer>(exec);
    for(int i = 0 ; i < 15 ; i++){
        compService.submit(new Callable<Integer>(){
            @Override
            public Integer call() throws Exception {
                return memo.compute(5);
            }
        });
    }
    exec.shutdown();
    for(int i = 0 ; i < 15 ; i++){
        System.out.println(compService.take().get());
    }
}

因此,如果两个线程尝试计算相同的阶乘完全相同的时间,只有其中一个将实际执行计算,因为 putIfAbsent 是线程安全的。第二个线程将简单地获得由第一个线程放在地图中的未来,并等待它完成。

So if two threads try to compute the same factorial at exactly the same time, only one of them will actually perform the computation, because putIfAbsent is threadsafe. The second thread will simply get the future which was put in the map by the first thread and wait for it to finish.

这篇关于在Java并发实践中由Brian Goetz的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆