Print this page
Split |
Close |
Expand all |
Collapse all |
--- old/test/java/lang/Thread/ThreadStateTest.java
+++ new/test/java/lang/Thread/ThreadStateTest.java
1 1 /*
2 - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved.
2 + * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
3 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 4 *
5 5 * This code is free software; you can redistribute it and/or modify it
6 6 * under the terms of the GNU General Public License version 2 only, as
7 7 * published by the Free Software Foundation.
8 8 *
9 9 * This code is distributed in the hope that it will be useful, but WITHOUT
10 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
12 12 * version 2 for more details (a copy is included in the LICENSE file that
13 13 * accompanied this code).
14 14 *
15 15 * You should have received a copy of the GNU General Public License version
16 16 * 2 along with this work; if not, write to the Free Software Foundation,
17 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18 18 *
19 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20 20 * or visit www.oracle.com if you need additional information or have any
21 21 * questions.
22 22 */
23 23
24 24 /*
25 25 * @test
26 26 * @bug 5014783
↓ open down ↓ |
14 lines elided |
↑ open up ↑ |
27 27 * @summary Basic unit test of thread states returned by
28 28 * Thread.getState().
29 29 *
30 30 * @author Mandy Chung
31 31 *
32 32 * @build ThreadStateTest
33 33 * @run main ThreadStateTest
34 34 */
35 35
36 36 import java.util.concurrent.locks.LockSupport;
37 -import java.util.concurrent.Semaphore;
37 +import java.util.concurrent.Phaser;
38 38
39 39 public class ThreadStateTest {
40 + // maximum number of retries when checking for thread state.
41 + static final int MAX_RETRY = 500;
42 +
40 43 private static boolean testFailed = false;
41 44
42 - static class Lock {
43 - private String name;
44 - Lock(String name) {
45 - this.name = name;
46 - }
47 - public String toString() {
48 - return name;
49 - }
50 - }
51 - private static Lock globalLock = new Lock("my lock");
45 + // used to achieve waiting states
46 + static final Object globalLock = new Object();
52 47
53 48 public static void main(String[] argv) {
54 49 // Call Thread.getState to force all initialization done
55 50 // before test verification begins.
56 51 Thread.currentThread().getState();
57 52 MyThread myThread = new MyThread("MyThread");
58 53
59 54 // before myThread starts
60 55 checkThreadState(myThread, Thread.State.NEW);
61 56
62 57 myThread.start();
63 58 myThread.waitUntilStarted();
64 59 checkThreadState(myThread, Thread.State.RUNNABLE);
65 60
66 61 synchronized (globalLock) {
67 62 myThread.goBlocked();
68 63 checkThreadState(myThread, Thread.State.BLOCKED);
69 64 }
70 65
71 66 myThread.goWaiting();
72 67 checkThreadState(myThread, Thread.State.WAITING);
73 68
74 69 myThread.goTimedWaiting();
75 70 checkThreadState(myThread, Thread.State.TIMED_WAITING);
76 71
77 72
78 73 /*
79 74 *********** park and parkUntil seems not working
80 75 * ignore this case for now.
81 76 * Bug ID 5062095
82 77 ***********************************************
83 78
84 79 myThread.goParked();
85 80 checkThreadState(myThread, Thread.State.WAITING);
↓ open down ↓ |
24 lines elided |
↑ open up ↑ |
86 81
87 82 myThread.goTimedParked();
88 83 checkThreadState(myThread, Thread.State.TIMED_WAITING);
89 84 */
90 85
91 86
92 87 myThread.goSleeping();
93 88 checkThreadState(myThread, Thread.State.TIMED_WAITING);
94 89
95 90 myThread.terminate();
96 - checkThreadState(myThread, Thread.State.TERMINATED);
97 -
98 91 try {
99 92 myThread.join();
100 93 } catch (InterruptedException e) {
101 94 e.printStackTrace();
102 95 System.out.println("Unexpected exception.");
103 96 testFailed = true;
104 97 }
98 + checkThreadState(myThread, Thread.State.TERMINATED);
99 +
100 +
105 101 if (testFailed)
106 102 throw new RuntimeException("TEST FAILED.");
107 103 System.out.println("Test passed.");
108 104 }
109 105
110 106 private static void checkThreadState(Thread t, Thread.State expected) {
111 - Thread.State state = t.getState();
107 + // wait for the thread to transition to the expected state.
108 + // There is a small window between the thread checking the state
109 + // and the thread actual entering that state.
110 + Thread.State state;
111 + int retryCount=0;
112 + while ((state = t.getState()) != expected && retryCount < MAX_RETRY) {
113 + if (state != Thread.State.RUNNABLE) {
114 + throw new RuntimeException("Thread not in expected state yet," +
115 + " but it should at least be RUNNABLE");
116 + }
117 + goSleep(10);
118 + retryCount++;
119 + }
120 +
112 121 System.out.println("Checking thread state " + state);
113 122 if (state == null) {
114 123 throw new RuntimeException(t.getName() + " expected to have " +
115 124 expected + " but got null.");
116 125 }
117 126
118 127 if (state != expected) {
119 128 throw new RuntimeException(t.getName() + " expected to have " +
120 129 expected + " but got " + state);
121 130 }
122 131 }
123 132
124 - private static String getLockName(Object lock) {
125 - if (lock == null) return null;
126 -
127 - return lock.getClass().getName() + '@' +
128 - Integer.toHexString(System.identityHashCode(lock));
129 - }
130 -
131 133 private static void goSleep(long ms) {
132 134 try {
133 135 Thread.sleep(ms);
134 136 } catch (InterruptedException e) {
135 137 e.printStackTrace();
136 138 System.out.println("Unexpected exception.");
137 139 testFailed = true;
138 140 }
139 141 }
140 142
141 143 static class MyThread extends Thread {
142 - private ThreadExecutionSynchronizer thrsync = new ThreadExecutionSynchronizer();
144 + // Phaser to sync between the main thread putting
145 + // this thread into various states
146 + private Phaser phaser = new Phaser(2);
143 147
144 148 MyThread(String name) {
145 149 super(name);
146 150 }
147 151
148 152 private final int RUNNABLE = 0;
149 153 private final int BLOCKED = 1;
150 154 private final int WAITING = 2;
151 155 private final int TIMED_WAITING = 3;
152 156 private final int PARKED = 4;
153 157 private final int TIMED_PARKED = 5;
154 158 private final int SLEEPING = 6;
155 159 private final int TERMINATE = 7;
156 - private int state = RUNNABLE;
160 +
161 + private volatile int state = RUNNABLE;
157 162
158 163 private boolean done = false;
159 164 public void run() {
160 165 // Signal main thread to continue.
161 - thrsync.signal();
166 + phaser.arriveAndAwaitAdvance();
167 +
162 168 while (!done) {
163 169 switch (state) {
164 170 case RUNNABLE: {
165 171 double sum = 0;
166 172 for (int i = 0; i < 1000; i++) {
167 173 double r = Math.random();
168 174 double x = Math.pow(3, r);
169 175 sum += x - r;
170 176 }
171 177 break;
172 178 }
173 179 case BLOCKED: {
174 180 // signal main thread.
175 - thrsync.signal();
181 + phaser.arrive();
176 182 System.out.println(" myThread is going to block.");
177 183 synchronized (globalLock) {
178 184 // finish blocking
179 185 state = RUNNABLE;
180 186 }
181 187 break;
182 188 }
183 189 case WAITING: {
184 190 synchronized (globalLock) {
185 191 // signal main thread.
186 - thrsync.signal();
192 + phaser.arrive();
187 193 System.out.println(" myThread is going to wait.");
188 194 try {
189 195 globalLock.wait();
190 196 } catch (InterruptedException e) {
191 197 // ignore
192 198 }
193 199 }
194 200 break;
195 201 }
196 202 case TIMED_WAITING: {
197 203 synchronized (globalLock) {
198 204 // signal main thread.
199 - thrsync.signal();
205 + phaser.arrive();
200 206 System.out.println(" myThread is going to timed wait.");
201 207 try {
202 208 globalLock.wait(10000);
203 209 } catch (InterruptedException e) {
204 210 // ignore
205 211 }
206 212 }
207 213 break;
208 214 }
209 215 case PARKED: {
210 216 // signal main thread.
211 - thrsync.signal();
217 + phaser.arrive();
212 218 System.out.println(" myThread is going to park.");
213 219 LockSupport.park();
214 220 // give a chance for the main thread to block
215 221 goSleep(10);
216 222 break;
217 223 }
218 224 case TIMED_PARKED: {
219 225 // signal main thread.
220 - thrsync.signal();
226 + phaser.arrive();
221 227 System.out.println(" myThread is going to timed park.");
222 228 long deadline = System.currentTimeMillis() + 10000*1000;
223 229 LockSupport.parkUntil(deadline);
224 230
225 231 // give a chance for the main thread to block
226 232 goSleep(10);
227 233 break;
228 234 }
229 235 case SLEEPING: {
230 236 // signal main thread.
231 - thrsync.signal();
237 + phaser.arrive();
232 238 System.out.println(" myThread is going to sleep.");
233 239 try {
234 240 Thread.sleep(1000000);
235 241 } catch (InterruptedException e) {
236 242 // finish sleeping
237 243 interrupted();
238 244 }
239 245 break;
240 246 }
241 247 case TERMINATE: {
242 248 done = true;
243 - // signal main thread.
244 - thrsync.signal();
245 249 break;
246 250 }
247 251 default:
248 252 break;
249 253 }
250 254 }
251 255 }
256 +
252 257 public void waitUntilStarted() {
253 258 // wait for MyThread.
254 - thrsync.waitForSignal();
255 - goSleep(10);
259 + phaser.arriveAndAwaitAdvance();
256 260 }
257 261
258 262 public void goBlocked() {
259 263 System.out.println("Waiting myThread to go blocked.");
260 264 setState(BLOCKED);
261 - // wait for MyThread to get blocked
262 - thrsync.waitForSignal();
263 - goSleep(20);
265 + // wait for MyThread to get to a point just before being blocked
266 + phaser.arriveAndAwaitAdvance();
264 267 }
265 268
266 269 public void goWaiting() {
267 270 System.out.println("Waiting myThread to go waiting.");
268 271 setState(WAITING);
269 - // wait for MyThread to wait on object.
270 - thrsync.waitForSignal();
271 - goSleep(20);
272 + // wait for MyThread to get to just before wait on object.
273 + phaser.arriveAndAwaitAdvance();
272 274 }
275 +
273 276 public void goTimedWaiting() {
274 277 System.out.println("Waiting myThread to go timed waiting.");
275 278 setState(TIMED_WAITING);
276 - // wait for MyThread timed wait call.
277 - thrsync.waitForSignal();
278 - goSleep(20);
279 + // wait for MyThread to get to just before timed wait call.
280 + phaser.arriveAndAwaitAdvance();
279 281 }
282 +
280 283 public void goParked() {
281 284 System.out.println("Waiting myThread to go parked.");
282 285 setState(PARKED);
283 - // wait for MyThread state change to PARKED.
284 - thrsync.waitForSignal();
285 - goSleep(20);
286 + // wait for MyThread to get to just before parked.
287 + phaser.arriveAndAwaitAdvance();
286 288 }
289 +
287 290 public void goTimedParked() {
288 291 System.out.println("Waiting myThread to go timed parked.");
289 292 setState(TIMED_PARKED);
290 - // wait for MyThread.
291 - thrsync.waitForSignal();
292 - goSleep(20);
293 + // wait for MyThread to get to just before timed park.
294 + phaser.arriveAndAwaitAdvance();
293 295 }
294 296
295 297 public void goSleeping() {
296 298 System.out.println("Waiting myThread to go sleeping.");
297 299 setState(SLEEPING);
298 - // wait for MyThread.
299 - thrsync.waitForSignal();
300 - goSleep(20);
300 + // wait for MyThread to get to just before sleeping
301 + phaser.arriveAndAwaitAdvance();
301 302 }
303 +
302 304 public void terminate() {
303 305 System.out.println("Waiting myThread to terminate.");
304 306 setState(TERMINATE);
305 - // wait for MyThread.
306 - thrsync.waitForSignal();
307 - goSleep(20);
308 307 }
309 308
310 309 private void setState(int newState) {
311 310 switch (state) {
312 311 case BLOCKED:
313 312 while (state == BLOCKED) {
314 313 goSleep(20);
315 314 }
316 315 state = newState;
317 316 break;
318 317 case WAITING:
319 318 case TIMED_WAITING:
320 319 state = newState;
321 320 synchronized (globalLock) {
322 321 globalLock.notify();
323 322 }
324 323 break;
325 324 case PARKED:
326 325 case TIMED_PARKED:
327 326 state = newState;
328 327 LockSupport.unpark(this);
329 328 break;
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
330 329 case SLEEPING:
331 330 state = newState;
332 331 this.interrupt();
333 332 break;
334 333 default:
335 334 state = newState;
336 335 break;
337 336 }
338 337 }
339 338 }
340 -
341 -
342 -
343 - static class ThreadExecutionSynchronizer {
344 -
345 - private boolean waiting;
346 - private Semaphore semaphore;
347 -
348 - public ThreadExecutionSynchronizer() {
349 - semaphore = new Semaphore(1);
350 - waiting = false;
351 - }
352 -
353 - // Synchronizes two threads execution points.
354 - // Basically any thread could get scheduled to run and
355 - // it is not possible to know which thread reaches expected
356 - // execution point. So whichever thread reaches a execution
357 - // point first wait for the second thread. When the second thread
358 - // reaches the expected execution point will wake up
359 - // the thread which is waiting here.
360 - void stopOrGo() {
361 - semaphore.acquireUninterruptibly(); // Thread can get blocked.
362 - if (!waiting) {
363 - waiting = true;
364 - // Wait for second thread to enter this method.
365 - while(!semaphore.hasQueuedThreads()) {
366 - try {
367 - Thread.sleep(20);
368 - } catch (InterruptedException xx) {}
369 - }
370 - semaphore.release();
371 - } else {
372 - waiting = false;
373 - semaphore.release();
374 - }
375 - }
376 -
377 - // Wrapper function just for code readability.
378 - void waitForSignal() {
379 - stopOrGo();
380 - }
381 -
382 - void signal() {
383 - stopOrGo();
384 - }
385 - }
386 339 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX