public static ByteBufferIndexInput newInstance( String resourceDescription, ByteBuffer[] buffers, long length, int chunkSizePower, BufferCleaner cleaner, boolean trackClones) { final WeakIdentityMap<ByteBufferIndexInput, Boolean> clones = trackClones ? WeakIdentityMap.<ByteBufferIndexInput, Boolean>newConcurrentHashMap() : null; if (buffers.length == 1) { return new SingleBufferImpl( resourceDescription, buffers[0], length, chunkSizePower, cleaner, clones); } else { return new DefaultImpl(resourceDescription, buffers, length, chunkSizePower, cleaner, clones); } }
public void testConcurrentHashMap() throws Exception { // don't make threadCount and keyCount random, otherwise easily OOMs or fails otherwise: final int threadCount = 8, keyCount = 1024; final ExecutorService exec = Executors.newFixedThreadPool(threadCount, new NamedThreadFactory("testConcurrentHashMap")); final WeakIdentityMap<Object, Integer> map = WeakIdentityMap.newConcurrentHashMap(random().nextBoolean()); // we keep strong references to the keys, // so WeakIdentityMap will not forget about them: final AtomicReferenceArray<Object> keys = new AtomicReferenceArray<Object>(keyCount); for (int j = 0; j < keyCount; j++) { keys.set(j, new Object()); } try { for (int t = 0; t < threadCount; t++) { final Random rnd = new Random(random().nextLong()); exec.execute( new Runnable() { @Override public void run() { final int count = atLeast(rnd, 10000); for (int i = 0; i < count; i++) { final int j = rnd.nextInt(keyCount); switch (rnd.nextInt(5)) { case 0: map.put(keys.get(j), Integer.valueOf(j)); break; case 1: final Integer v = map.get(keys.get(j)); if (v != null) { assertEquals(j, v.intValue()); } break; case 2: map.remove(keys.get(j)); break; case 3: // renew key, the old one will be GCed at some time: keys.set(j, new Object()); break; case 4: // check iterator still working for (Iterator<Object> it = map.keyIterator(); it.hasNext(); ) { assertNotNull(it.next()); } break; default: fail("Should not get here."); } } } }); } } finally { exec.shutdown(); while (!exec.awaitTermination(1000L, TimeUnit.MILLISECONDS)) ; } // clear strong refs for (int j = 0; j < keyCount; j++) { keys.set(j, null); } // check that GC does not cause problems in reap() method: int size = map.size(); for (int i = 0; size > 0 && i < 10; i++) try { System.runFinalization(); System.gc(); int newSize = map.size(); assertTrue("previousSize(" + size + ")>=newSize(" + newSize + ")", size >= newSize); size = newSize; Thread.sleep(100L); int c = 0; for (Iterator<Object> it = map.keyIterator(); it.hasNext(); ) { assertNotNull(it.next()); c++; } newSize = map.size(); assertTrue("previousSize(" + size + ")>=iteratorSize(" + c + ")", size >= c); assertTrue("iteratorSize(" + c + ")>=newSize(" + newSize + ")", c >= newSize); size = newSize; } catch (InterruptedException ie) { } }