|
1 | 1 | import java.util.*;
|
| 2 | +import java.util.concurrent.ConcurrentLinkedQueue; |
2 | 3 |
|
3 | 4 | class Main {
|
4 |
| - static Deque<Integer> queue; |
5 |
| - static CombiningTree<Integer> concurrentQueue; |
6 |
| - static List<Integer>[] deqValues; |
7 |
| - static int TH = 10, NUM = 1000; |
8 |
| - |
9 |
| - // Each unsafe thread enqs N numbers and deqs N, adding |
10 |
| - // them to its own deqValues for checking; using Java's |
11 |
| - // sequential queue implementation, ArrayDeque. |
12 |
| - static Thread unsafe(int id, int x, int N) { |
13 |
| - return new Thread(() -> { |
14 |
| - String action = "enq"; |
15 |
| - try { |
16 |
| - for (int i=0, y=x; i<N; i++) |
17 |
| - queue.addLast(y++); |
18 |
| - Thread.sleep(1000); |
19 |
| - action = "deq"; |
20 |
| - for (int i=0; i<N; i++) |
21 |
| - deqValues[id].add(queue.removeFirst()); |
22 |
| - } |
23 |
| - catch (Exception e) { log(id+": failed "+action); } |
24 |
| - }); |
25 |
| - } |
| 5 | + static Queue<Integer> queue; |
| 6 | + static CombiningTree<Integer> tree; |
| 7 | + static int TH = 8, NUM = 10; |
26 | 8 |
|
27 | 9 | // Each safe thread enqs N numbers and deqs N, adding
|
28 | 10 | // them to its own deqValues for checking; using
|
29 | 11 | // ArrayQueue.
|
30 |
| - static Thread safe(int id, int x, int N) { |
| 12 | + static Thread thread(int id) { |
31 | 13 | return new Thread(() -> {
|
32 |
| - String action = "enq"; |
33 | 14 | try {
|
34 |
| - for (int i=0, y=x; i<N; i++) |
35 |
| - concurrentQueue.enq(y++); |
36 |
| - Thread.sleep(1000); |
37 |
| - action = "deq"; |
38 |
| - for (int i=0; i<N; i++) |
39 |
| - deqValues[id].add(concurrentQueue.deq()); |
| 15 | + for (int i=0; i<NUM; i++) { |
| 16 | + Integer r = tree.getAndOp(1, |
| 17 | + (Integer x, Integer y) -> x); |
| 18 | + queue.add(r); |
40 | 19 | }
|
41 |
| - catch (Exception e) { log(id+": failed "+action); |
42 |
| - e.printStackTrace(); } |
| 20 | + } catch (InterruptedException e) {} |
43 | 21 | });
|
44 | 22 | }
|
45 | 23 |
|
46 | 24 | // Checks if each thread dequeued N values, and they are
|
47 | 25 | // globally unique.
|
48 |
| - static boolean wasLIFO(int N) { |
49 |
| - Set<Integer> set = new HashSet<>(); |
50 |
| - boolean passed = true; |
51 |
| - for (int i=0; i<TH; i++) { |
52 |
| - int n = deqValues[i].size(); |
53 |
| - if (n != N) { |
54 |
| - log(i+": dequeued "+n+"/"+N+" values"); |
55 |
| - passed = false; |
56 |
| - } |
57 |
| - for (Integer x : deqValues[i]) |
58 |
| - if (set.contains(x)) { |
59 |
| - log(i+": has duplicate value "+x); |
60 |
| - passed = false; |
61 |
| - } |
62 |
| - set.addAll(deqValues[i]); |
| 26 | + static boolean wasValid() { |
| 27 | + int a = tree.get().intValue(); |
| 28 | + if (a != TH*NUM) return false; |
| 29 | + Set<Integer> s = new HashSet<>(); |
| 30 | + while (queue.size()>0) { |
| 31 | + Integer n = queue.remove(); |
| 32 | + if (s.contains(n)) return false; |
| 33 | + s.add(n); |
63 | 34 | }
|
64 |
| - return passed; |
| 35 | + return true; |
65 | 36 | }
|
66 | 37 |
|
67 |
| - @SuppressWarnings("unchecked") |
68 |
| - static void testThreads(boolean safe) { |
69 |
| - queue = new ArrayDeque<>(); |
70 |
| - concurrentQueue = new CombiningTree<>(TH*NUM); |
71 |
| - deqValues = new List[TH]; |
| 38 | + static Thread[] startOps() { |
| 39 | + Thread[] t = new Thread[TH]; |
72 | 40 | for (int i=0; i<TH; i++)
|
73 |
| - deqValues[i] = new ArrayList<>(); |
74 |
| - Thread[] threads = new Thread[TH]; |
75 |
| - for (int i=0; i<TH; i++) { |
76 |
| - threads[i] = safe? |
77 |
| - safe(i, i*NUM, NUM) : |
78 |
| - unsafe(i, i*NUM, NUM); |
79 |
| - threads[i].start(); |
80 |
| - } |
| 41 | + t[i] = thread(i); |
| 42 | + for (int i=0; i<TH; i++) |
| 43 | + t[i].start(); |
| 44 | + return t; |
| 45 | + } |
| 46 | + |
| 47 | + static void awaitOps(Thread[] t) { |
81 | 48 | try {
|
82 | 49 | for (int i=0; i<TH; i++)
|
83 |
| - threads[i].join(); |
84 |
| - } |
85 |
| - catch (Exception e) {} |
| 50 | + t[i].join(); |
| 51 | + } catch (InterruptedException e) {} |
86 | 52 | }
|
87 | 53 |
|
88 | 54 | public static void main(String[] args) {
|
89 |
| - log("Starting "+TH+" threads with sequential queue"); |
90 |
| - testThreads(false); |
91 |
| - log("Was LIFO? "+wasLIFO(NUM)); |
92 |
| - log(""); |
93 |
| - log("Starting "+TH+" threads with array queue"); |
94 |
| - testThreads(true); |
95 |
| - log("Was LIFO? "+wasLIFO(NUM)); |
96 |
| - log(""); |
| 55 | + queue = new ConcurrentLinkedQueue<>(); |
| 56 | + tree = new CombiningTree<>(3); |
| 57 | + tree.set(0); |
| 58 | + log("Starting "+TH+" threads doing ops ..."); |
| 59 | + Thread[] t = startOps(); |
| 60 | + awaitOps(t); |
| 61 | + log("\nWas valid? "+wasValid()); |
97 | 62 | }
|
98 | 63 |
|
99 | 64 | static void log(String x) {
|
|
0 commit comments