Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

In Java Concurrency In Practice by 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());
            }
        }
    } }

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

Cheers, Agata

like image 305
Agata Avatar asked Feb 03 '11 13:02

Agata


People also ask

Is Java Concurrency in Practice still valid?

TL: DR — Yes, Java Concurrency in Practice is still valid and one of the best books to learn Java multithreading and concurrency concepts.

What is concurrency in Java?

Concurrency is the ability to run several or multi programs or applications in parallel. The backbone of Java concurrency is threads (a lightweight process, which has its own files and stacks and can access the shared data from other threads in the same process).

How do you handle concurrency in Java?

The simplest way to avoid problems with concurrency is to share only immutable data between threads. Immutable data is data which cannot be changed. To make a class immutable define the class and all its fields as final. Also ensure that no reference to fields escape during construction.

Does Java have concurrency?

The Java platform is designed from the ground up to support concurrent programming, with basic concurrency support in the Java programming language and the Java class libraries. Since version 5.0, the Java platform has also included high-level concurrency APIs.


2 Answers

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());
    }
}

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.

like image 67
dogbane Avatar answered Nov 13 '22 02:11

dogbane


I could imagine something like this:

class PrimeDetector implements Computable<BigInteger, Boolean> {
  public Boolean compute(BigInteger number) {
    // detect whether the number is prime and return true if it is
  }
}

Memoizer<BigInteger, Boolean> primeMemoizer =
        new Memoizer<BigInteger, BigInteger[]>(new PrimeDetector());
boolean isPrime = primeMemoizer.compute(
        new BigInteger("5625945193217348954671586615478165774647538956473535"));
...
like image 20
Péter Török Avatar answered Nov 13 '22 03:11

Péter Török