CircularList { public void swapWithList(Collection<T> newList) { InnerList newInnerList = new InnerList(newList); ref.set(newInnerList); } CircularList(Collection<T> origList); T getNextElement(); void swapWithList(Collection<T> newList); synchronized void addElement(T element); synchronized void removeElement(T element); List<T> getEntireList(); int getSize();  }
@Test public void testSingleThreadWithElementAdd() throws Exception { final AtomicBoolean stop = new AtomicBoolean(false); Future<Map<Integer, Integer>> future = threadPool.submit(new Callable<Map<Integer, Integer>>() { @Override public Map<Integer, Integer> call() throws Exception { TestWorker worker = new TestWorker(); while (!stop.get()) { worker.process(); } return worker.map; } }); Thread.sleep(500); List<Integer> newList = new ArrayList<Integer>(); newList.addAll(iList); for (int i = 10; i < 15; i++) { newList.add(i); } cList.swapWithList(newList); Thread.sleep(100); stop.set(true); Map<Integer, Integer> result = future.get(); Map<Integer, Integer> subMap = CollectionUtils.filterKeys(result, new Predicate<Integer>() { @Override public boolean apply(Integer input) { return input != null && input < 10; } }); List<Integer> list = new ArrayList<Integer>(subMap.values()); checkValues(list); subMap = CollectionUtils.difference(result, subMap).entriesOnlyOnLeft(); list = new ArrayList<Integer>(subMap.values()); checkValues(list); }
@Test public void testSingleThreadWithElementRemove() throws Exception { final AtomicBoolean stop = new AtomicBoolean(false); Future<Map<Integer, Integer>> future = threadPool.submit(new Callable<Map<Integer, Integer>>() { @Override public Map<Integer, Integer> call() throws Exception { TestWorker worker = new TestWorker(); while (!stop.get()) { worker.process(); } return worker.map; } }); Thread.sleep(200); List<Integer> newList = new ArrayList<Integer>(); newList.addAll(iList); final List<Integer> removedElements = new ArrayList<Integer>(); removedElements.add(newList.remove(2)); removedElements.add(newList.remove(5)); removedElements.add(newList.remove(6)); cList.swapWithList(newList); Thread.sleep(200); stop.set(true); Map<Integer, Integer> result = future.get(); Map<Integer, Integer> subMap = CollectionUtils.filterKeys(result, new Predicate<Integer>() { @Override public boolean apply(Integer input) { return !removedElements.contains(input); } }); checkValues(new ArrayList<Integer>(subMap.values())); }
@Test public void testMultipleThreadsWithElementAdd() throws Exception { final AtomicBoolean stop = new AtomicBoolean(false); final CyclicBarrier barrier = new CyclicBarrier(5); final List<Future<Map<Integer, Integer>>> futures = new ArrayList<Future<Map<Integer, Integer>>>(); for (int i = 0; i < 5; i++) { futures.add(threadPool.submit(new Callable<Map<Integer, Integer>>() { @Override public Map<Integer, Integer> call() throws Exception { barrier.await(); TestWorker worker = new TestWorker(); while (!stop.get()) { worker.process(); } return worker.map; } })); } Thread.sleep(200); List<Integer> newList = new ArrayList<Integer>(iList); for (int i = 10; i < 15; i++) { newList.add(i); } cList.swapWithList(newList); Thread.sleep(200); stop.set(true); Map<Integer, Integer> result = getTotalMap(futures); Map<Integer, Integer> subMap = CollectionUtils.filterKeys(result, new Predicate<Integer>() { @Override public boolean apply(Integer input) { return input < 10; } }); checkValues(new ArrayList<Integer>(subMap.values())); subMap = CollectionUtils.difference(result, subMap).entriesOnlyOnLeft(); checkValues(new ArrayList<Integer>(subMap.values())); }
@Test public void testMultipleThreadsWithElementsRemoved() throws Exception { final AtomicBoolean stop = new AtomicBoolean(false); final CyclicBarrier barrier = new CyclicBarrier(5); final List<Future<Map<Integer, Integer>>> futures = new ArrayList<Future<Map<Integer, Integer>>>(); for (int i = 0; i < 5; i++) { futures.add(threadPool.submit(new Callable<Map<Integer, Integer>>() { @Override public Map<Integer, Integer> call() throws Exception { barrier.await(); TestWorker worker = new TestWorker(); while (!stop.get()) { worker.process(); } return worker.map; } })); } Thread.sleep(200); List<Integer> newList = new ArrayList<Integer>(iList); final List<Integer> removedElements = new ArrayList<Integer>(); removedElements.add(newList.remove(2)); removedElements.add(newList.remove(5)); removedElements.add(newList.remove(6)); cList.swapWithList(newList); Thread.sleep(200); stop.set(true); Map<Integer, Integer> result = getTotalMap(futures); Map<Integer, Integer> subMap = CollectionUtils.filterKeys(result, new Predicate<Integer>() { @Override public boolean apply(Integer x) { return !removedElements.contains(x); } }); checkValues(new ArrayList<Integer>(subMap.values())); }