-
Notifications
You must be signed in to change notification settings - Fork 554
/
KeyAtomicityTest.java
103 lines (94 loc) · 3.02 KB
/
KeyAtomicityTest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
package org.jctools.maps;
import java.util.*;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Test;
import static org.junit.Assert.assertEquals;
public class KeyAtomicityTest
{
static final int THREAD_SEGMENT = 1000000;
@Test
public void putReturnValuesAreDistinct() throws Exception
{
Map<String, Long> map = new NonBlockingHashMap<>();
map.put("K", -1l);
int processors = Runtime.getRuntime().availableProcessors();
CountDownLatch ready = new CountDownLatch(processors);
CountDownLatch start = new CountDownLatch(1);
CountDownLatch done = new CountDownLatch(processors);
AtomicBoolean keepRunning = new AtomicBoolean(true);
PutKey[] putKeys = new PutKey[processors];
for (int i = 0; i < processors; i++)
{
putKeys[i] = new PutKey(map, "K", keepRunning, ready, start, done, i * THREAD_SEGMENT);
Thread t = new Thread(putKeys[i]);
t.setName("Putty McPutkey-"+i);
t.start();
}
ready.await();
start.countDown();
Thread.sleep(1000);
keepRunning.set(false);
done.await();
Set<Long> values = new HashSet((int)(processors*THREAD_SEGMENT));
long totalKeys = 0;
for (PutKey putKey : putKeys)
{
values.addAll(putKey.values);
totalKeys += putKey.endIndex - putKey.startIndex;
}
assertEquals(totalKeys, values.size());
}
static class PutKey implements Runnable
{
final Map<String, Long> map;
final String key;
final AtomicBoolean keepRunning;
final CountDownLatch ready;
final CountDownLatch start;
final CountDownLatch done;
final int startIndex;
int endIndex;
List<Long> values = new ArrayList<>(THREAD_SEGMENT);
PutKey(
Map<String, Long> map,
String key,
AtomicBoolean keepRunning, CountDownLatch ready,
CountDownLatch start,
CountDownLatch done,
int startIndex)
{
this.map = map;
this.key = key;
this.keepRunning = keepRunning;
this.ready = ready;
this.start = start;
this.done = done;
this.startIndex = startIndex;
assert startIndex >= 0 && startIndex + THREAD_SEGMENT > 0;
}
@Override
public void run()
{
ready.countDown();
try
{
start.await();
}
catch (InterruptedException e)
{
e.printStackTrace();
return;
}
long limit = startIndex + THREAD_SEGMENT;
long v = startIndex;
String k = key;
for (; v < limit && keepRunning.get(); v++)
{
values.add(map.put(k, v));
}
endIndex = (int) v;
done.countDown();
}
}
}