1 package org.slf4j.basicTests;
2
3 import java.util.concurrent.BrokenBarrierException;
4 import java.util.concurrent.CyclicBarrier;
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 public class DoubleCheckedInt {
20
21 final static int THREAD_COUNT = 10 + Runtime.getRuntime().availableProcessors() * 2;
22 final static int UNINITIALIZED_STATE = 0;
23 final static int ONGOING_INITIALIZATION = 1;
24 final static int SUCCESS = 2;
25 final static int FAILURE = 3;
26 final static int NUMBER_OF_STATES = FAILURE + 1;
27
28 private static int STATE = UNINITIALIZED_STATE;
29
30 public static int getState() {
31 if (STATE == 0) {
32 synchronized (DoubleCheckedInt.class) {
33 if (STATE == UNINITIALIZED_STATE) {
34 STATE = ONGOING_INITIALIZATION;
35 long r = System.nanoTime();
36 try {
37 Thread.sleep(10);
38 } catch (InterruptedException e) {
39 }
40 if (r % 2 == 0) {
41 STATE = SUCCESS;
42 } else {
43 STATE = FAILURE;
44 }
45 }
46 }
47 }
48 return STATE;
49 }
50
51 static public void main(String[] args) throws InterruptedException, BrokenBarrierException {
52 StateAccessingThread[] preInitializationThreads = harness();
53 check(preInitializationThreads, false);
54
55 System.out.println("============");
56 StateAccessingThread[] postInitializationThreads = harness();
57 check(postInitializationThreads, true);
58 }
59
60 private static StateAccessingThread[] harness() throws InterruptedException, BrokenBarrierException {
61 StateAccessingThread[] threads = new StateAccessingThread[THREAD_COUNT];
62 final CyclicBarrier barrier = new CyclicBarrier(THREAD_COUNT + 1);
63 for (int i = 0; i < THREAD_COUNT; i++) {
64 threads[i] = new StateAccessingThread(barrier);
65 threads[i].start();
66 }
67
68 barrier.await();
69 for (int i = 0; i < THREAD_COUNT; i++) {
70 threads[i].join();
71 }
72 return threads;
73 }
74
75 private static void check(StateAccessingThread[] threads, boolean postInit) {
76
77 int[] stateCount = getStateCount(threads);
78 printStateCount(stateCount);
79
80 if (stateCount[UNINITIALIZED_STATE] != 0) {
81 throw new IllegalStateException("getState() should never return a zero value");
82 }
83
84 if (stateCount[SUCCESS] != 0 && stateCount[FAILURE] != 0) {
85 throw new IllegalStateException("getState() should return consistent values");
86 }
87
88 if (postInit) {
89 if (stateCount[SUCCESS] != THREAD_COUNT && stateCount[FAILURE] != THREAD_COUNT) {
90 throw new IllegalStateException("getState() should return consistent values");
91 }
92 }
93
94 }
95
96 private static void printStateCount(int[] stateCount) {
97 for (int i = 0; i < NUMBER_OF_STATES; i++) {
98 switch (i) {
99 case UNINITIALIZED_STATE:
100 System.out.println("UNINITIALIZED_STATE count: " + stateCount[i]);
101 break;
102 case ONGOING_INITIALIZATION:
103 System.out.println("ONGOING_INITIALIZATION count: " + stateCount[i]);
104 break;
105 case SUCCESS:
106 System.out.println("SUCCESS count: " + stateCount[i]);
107 break;
108 case FAILURE:
109 System.out.println("FAILURE count: " + stateCount[i]);
110 break;
111 }
112 }
113 }
114
115 private static int[] getStateCount(StateAccessingThread[] threads) {
116 int[] valCount = new int[NUMBER_OF_STATES];
117 for (StateAccessingThread thread : threads) {
118 int val = thread.state;
119 valCount[val] = valCount[val] + 1;
120 }
121 return valCount;
122 }
123
124 static class StateAccessingThread extends Thread {
125 public int state = -1;
126 final CyclicBarrier barrier;
127
128 StateAccessingThread(CyclicBarrier barrier) {
129 this.barrier = barrier;
130 }
131
132 public void run() {
133 try {
134 barrier.await();
135 } catch (Exception e) {
136 e.printStackTrace();
137 }
138 state = DoubleCheckedInt.getState();
139 }
140 };
141 }