2011-02-03 13 views
7

Java Concurrency In Practice di Brian Goetz fornisce un esempio di efficiente cache scalabile per uso simultaneo. Ecco il codice per la classe:In Java Concurrency In Practice di Brian Goetz

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

Probabilmente una domanda stupida, ma nessuna indicazione qualcuno mi mostrano l'utilizzo concomitante di questa classe? Come in una main?

Cheers, Agata

+0

Potresti essere interessato anche a Google Guava MapMaker - http://guava-libraries.googlecode.com/svn/trunk/javadoc/com/google/common/collect/MapMaker.html. –

risposta

6

Ecco un esempio che calcola fattoriali:

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

Quindi, se due thread cercano di calcolare la stessa fattoriale esattamente allo stesso tempo, solo uno di loro eseguirà effettivamente il calcolo, perché putIfAbsent è thread-safe. Il secondo thread otterrà semplicemente il futuro che è stato inserito nella mappa dal primo thread e aspetta che finisca.

+0

Grazie anche per la risposta - lo farò studiarlo :) – Agata

+0

+1 per l'esempio più completo. –

1

potrei immaginare qualcosa di simile:

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")); 
... 
+0

Ciao, grazie per la risposta. Questo è quello che mi è venuto in mente, ma quello che non capisco è come viene usato contemporaneamente? Voglio dire che hai creato un PrimeDetector, lo metti in Memoizer ma se avessi più oggetti come PrimeDetector e voglio che tutti usino il Memorizzatore e calcolino in parallelo. Quando imposto un oggetto Computable in Memorizer, non potrò cambiarlo né usarlo con oggetti Computable diversi in una volta. Questo è quello che non capisco :( – Agata

+0

Forse la mia spiegazione non è la più chiara .. Generalmente non capisco come dovrebbe funzionare contemporaneamente – Agata

+0

Qual è il problema? Si può usare per un solo Computable, ma tu È possibile testare simultaneamente molti numeri primi – maaartinus

Problemi correlati