Learning Code – Concurrent solution



Learning Code – Concurrent solution

Building an Efficient, Scalable Result Cache
Caching a Future instead of a value creates the possibility of cache pollution: if a computation is cancelled or fails, future attempts to compute the result will also indicate cancellation or failure. To avoid this, Memoizer removes the Future from the cache if it detects that the computation was cancelled; it might also be desirable to remove the Future upon detecting a RuntimeException if the computation might succeed on a future attempt.
 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.launderThrowable(e.getCause());  
                }  
           }  
      }  
 }  
Turn collections into bounded collections.
 public class BoundedHashSet<T> {  
      private final Set<T> set;  
      private final Semaphore semaphore;  
      public BoundedHashSet(int bound) {  
           this.set = Collections.synchronizedSet(new HashSet<T>());  
           semaphore = new Semaphore(bound);  
      }  
      public boolean add(T o) throws InterruptedException {  
           semaphore.acquire();  
           boolean wasAdded = false;  
           try {  
                wasAdded = set.add(o);  
                return wasAdded;  
           } finally {  
                if (!wasAdded)  
                     semaphore.release();  
           }  
      }  
      public boolean remove(Object o) {  
           boolean wasRemoved = set.remove(o);  
           if (wasRemoved)  
                semaphore.release();  
           return wasRemoved;  
      }  
 }  

Use CompletionService to render page concurrently.

 public abstract class Renderer {  
      private final ExecutorService executor;  
      Renderer(ExecutorService executor) {  
           this.executor = executor;  
      }  
      void renderPage(CharSequence source) {  
           final List<ImageInfo> info = scanForImageInfo(source);  
           CompletionService<ImageData> completionService = new ExecutorCompletionService<ImageData>(  
                     executor);  
           for (final ImageInfo imageInfo : info)  
                completionService.submit(new Callable<ImageData>() {  
                     public ImageData call() {  
                          return imageInfo.downloadImage();  
                     }  
                });  
           renderText(source);  
           try {  
                for (int t = 0, n = info.size(); t < n; t++) {  
                     Future<ImageData> f = completionService.take();  
                     ImageData imageData = f.get();  
                     renderImage(imageData);  
                }  
           } catch (InterruptedException e) {  
                Thread.currentThread().interrupt();  
           } catch (ExecutionException e) {  
                throw LaunderThrowable.launderThrowable(e.getCause());  
           }  
      }  
      interface ImageData {  
      }  
      interface ImageInfo {  
           ImageData downloadImage();  
      }  
      abstract void renderText(CharSequence s);  
      abstract List<ImageInfo> scanForImageInfo(CharSequence s);  
      abstract void renderImage(ImageData i);  
 }  

Labels

adsense (5) Algorithm (69) Algorithm Series (35) Android (7) ANT (6) bat (8) Big Data (7) Blogger (14) Bugs (6) Cache (5) Chrome (19) Code Example (29) Code Quality (7) Coding Skills (5) Database (7) Debug (16) Design (5) Dev Tips (63) Eclipse (32) Git (5) Google (33) Guava (7) How to (9) Http Client (8) IDE (7) Interview (88) J2EE (13) J2SE (49) Java (186) JavaScript (27) JSON (7) Learning code (9) Lesson Learned (6) Linux (26) Lucene-Solr (112) Mac (10) Maven (8) Network (9) Nutch2 (18) Performance (9) PowerShell (11) Problem Solving (11) Programmer Skills (6) regex (5) Scala (6) Security (9) Soft Skills (38) Spring (22) System Design (11) Testing (7) Text Mining (14) Tips (17) Tools (24) Troubleshooting (29) UIMA (9) Web Development (19) Windows (21) xml (5)