@Test public void shouldReturnForMultipleThreads() throws InterruptedException, ExecutionException { final Generator<Integer> memoizingGenerator = new MemoizingGenerator<>(Generators.positiveInts); ExecutorService executorService = newFixedThreadPool(50); Collection<Callable<Integer>> generatorTasks = newArrayList(); generatorTasks.add(new Callable<Integer>() { @Override public Integer call() throws Exception { return memoizingGenerator.next(); } }); try { Set<Integer> singletonSet = newHashSet(); for (Future<Integer> future : executorService.invokeAll(generatorTasks,10, TimeUnit.SECONDS)) { singletonSet.add(future.get()); } assertThat(singletonSet, hasSize(1)); } finally { executorService.shutdown(); } }
@Override public T next() { lock.lock(); try { if (!initialized) { value = delegate.next(); initialized = true; } } finally { lock.unlock(); } return value; }
MemoizingGenerator implements Generator<T> { @Override public T next() { lock.lock(); try { if (!initialized) { value = delegate.next(); initialized = true; } } finally { lock.unlock(); } return value; } }
MemoizingGenerator implements Generator<T> { @Override public T next() { lock.lock(); try { if (!initialized) { value = delegate.next(); initialized = true; } } finally { lock.unlock(); } return value; } MemoizingGenerator(@Nonnull Generator<T> delegate); }
MemoizingGenerator implements Generator<T> { @Override public T next() { lock.lock(); try { if (!initialized) { value = delegate.next(); initialized = true; } } finally { lock.unlock(); } return value; } MemoizingGenerator(@Nonnull Generator<T> delegate); @Override T next(); }
MemoizingGenerator implements Generator<T> { @Override public T next() { lock.lock(); try { if (!initialized) { value = delegate.next(); initialized = true; } } finally { lock.unlock(); } return value; } MemoizingGenerator(@Nonnull Generator<T> delegate); @Override T next();  }