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