BAEL-5946: Reading and Writing With a ConcurrentHashMap (#13163)
* consistent read unit test * unit test to show consistency in writing to the same key of map * testing writes at different map key
This commit is contained in:
parent
88f2eca118
commit
6bb5598904
|
@ -0,0 +1,114 @@
|
|||
package com.baeldung.concurrenthashmap;
|
||||
|
||||
import org.junit.jupiter.api.AfterEach;
|
||||
import org.junit.jupiter.api.BeforeEach;
|
||||
import org.junit.jupiter.api.Test;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.*;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import static java.util.Arrays.asList;
|
||||
import static org.junit.jupiter.api.Assertions.assertEquals;
|
||||
|
||||
public class ConcurrentHashMapUnitTest {
|
||||
|
||||
private Map<Integer, Integer> frequencyMap;
|
||||
|
||||
@BeforeEach
|
||||
public void setup() {
|
||||
frequencyMap = new ConcurrentHashMap<>();
|
||||
frequencyMap.put(0, 0);
|
||||
frequencyMap.put(1, 0);
|
||||
frequencyMap.put(2, 0);
|
||||
}
|
||||
|
||||
@AfterEach
|
||||
public void teardown() {
|
||||
frequencyMap.clear();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenOneThreadIsWriting_whenAnotherThreadReads_thenGetCorrectValue() throws Exception {
|
||||
ExecutorService threadExecutor = Executors.newFixedThreadPool(3);
|
||||
|
||||
Runnable writeAfter1Sec = () -> frequencyMap.computeIfPresent(1, (k, v) -> {
|
||||
sleep(1);
|
||||
return frequencyMap.get(k) + 1;
|
||||
});
|
||||
|
||||
Callable<Integer> readNow = () -> frequencyMap.get(1);
|
||||
Callable<Integer> readAfter1001Ms = () -> {
|
||||
TimeUnit.MILLISECONDS.sleep(1001);
|
||||
return frequencyMap.get(1);
|
||||
};
|
||||
|
||||
threadExecutor.submit(writeAfter1Sec);
|
||||
List<Future<Integer>> results = threadExecutor.invokeAll(asList(readNow, readAfter1001Ms));
|
||||
|
||||
assertEquals(0, results.get(0).get());
|
||||
assertEquals(1, results.get(1).get());
|
||||
|
||||
if (threadExecutor.awaitTermination(2, TimeUnit.SECONDS)) {
|
||||
threadExecutor.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenOneThreadIsWriting_whenAnotherThreadWritesAtSameKey_thenWaitAndGetCorrectValue() throws Exception {
|
||||
ExecutorService threadExecutor = Executors.newFixedThreadPool(2);
|
||||
|
||||
Callable<Integer> writeAfter5Sec = () -> frequencyMap.computeIfPresent(1, (k, v) -> {
|
||||
sleep(5);
|
||||
return frequencyMap.get(k) + 1;
|
||||
});
|
||||
|
||||
Callable<Integer> writeAfter1Sec = () -> frequencyMap.computeIfPresent(1, (k, v) -> {
|
||||
sleep(1);
|
||||
return frequencyMap.get(k) + 1;
|
||||
});
|
||||
|
||||
List<Future<Integer>> results = threadExecutor.invokeAll(asList(writeAfter5Sec, writeAfter1Sec));
|
||||
|
||||
assertEquals(1, results.get(0).get());
|
||||
assertEquals(2, results.get(1).get());
|
||||
|
||||
if (threadExecutor.awaitTermination(2, TimeUnit.SECONDS)) {
|
||||
threadExecutor.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void givenOneThreadIsWriting_whenAnotherThreadWritesAtDifferentKey_thenNotWaitAndGetCorrectValue() throws Exception {
|
||||
ExecutorService threadExecutor = Executors.newFixedThreadPool(2);
|
||||
|
||||
Callable<Integer> writeAfter5Sec = () -> frequencyMap.computeIfPresent(1, (k, v) -> {
|
||||
sleep(5);
|
||||
return frequencyMap.get(k) + 1;
|
||||
});
|
||||
|
||||
AtomicLong time = new AtomicLong(System.currentTimeMillis());
|
||||
Callable<Integer> writeAfter1Sec = () -> frequencyMap.computeIfPresent(2, (k, v) -> {
|
||||
sleep(1);
|
||||
time.set((System.currentTimeMillis() - time.get()) / 1000);
|
||||
return frequencyMap.get(k) + 1;
|
||||
});
|
||||
|
||||
threadExecutor.invokeAll(asList(writeAfter5Sec, writeAfter1Sec));
|
||||
|
||||
assertEquals(1, time.get());
|
||||
|
||||
if (threadExecutor.awaitTermination(2, TimeUnit.SECONDS)) {
|
||||
threadExecutor.shutdown();
|
||||
}
|
||||
}
|
||||
|
||||
private static void sleep(int timeout) {
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(timeout);
|
||||
} catch (InterruptedException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue