import org.junit.Test; import org.junit.Assert; import java.util.TreeMap; import java.util.HashSet; import java.util.concurrent.Semaphore; import java.util.Random; import jelectrum.BandedUpdater; public class BandedUpdaterTest { @Test public void testBasic() { TreeMap<String, HashSet<String> > map=new TreeMap<String, HashSet<String>>(); BandedUpdater<String, String> bu = new BandedUpdater<String,String>(map,2); bu.addItem("a","cow"); bu.addItem("a","wolf"); bu.addItem("a","tomato"); Assert.assertEquals(1, map.size()); Assert.assertEquals(3, map.get("a").size()); bu.addItem("b","tomato"); Assert.assertEquals(2, map.size()); } @Test public void multiThreadTest() throws Exception { TreeMap<String, HashSet<String> > map=new DelayMap<String, HashSet<String>>(); BandedUpdater<String, String> bu = new BandedUpdater<String,String>(map,16); Semaphore sem = new Semaphore(0); for(int i=0; i<100; i++) { new InsertThread(bu, sem).start(); } sem.acquire(100); Assert.assertEquals(1, map.size()); Assert.assertEquals(1000, map.get("a").size()); } public class InsertThread extends Thread { BandedUpdater<String, String> bu; Semaphore sem; public InsertThread(BandedUpdater<String, String> bu, Semaphore sem) { this.bu = bu; this.sem = sem; } public void run() { Random rnd = new Random(); for(int i=0; i<10; i++) { bu.addItem("a", "" + rnd.nextDouble()); } sem.release(1); } } public class DelayMap<K,V> extends TreeMap<K,V> { public DelayMap() { super(); } private volatile int concur; @Override public V put(K k, V v) { concur++; for(int i=0; i<10; i++) { Assert.assertEquals(1,concur); try{Thread.sleep(10);}catch(Exception e){} } concur--; return super.put(k,v); } } }