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 8022208 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 private 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 myThread.setDaemon(true); 54 55 // before myThread starts 56 checkThreadState(myThread, Thread.State.NEW); 57 58 myThread.start(); 59 myThread.waitUntilStarted(); 60 checkThreadState(myThread, Thread.State.RUNNABLE); 61 62 synchronized (globalLock) { 63 myThread.goBlocked(); 64 checkThreadState(myThread, Thread.State.BLOCKED); 65 } 66 67 myThread.goWaiting(); 68 checkThreadState(myThread, Thread.State.WAITING); 69 70 myThread.goTimedWaiting(); 71 checkThreadState(myThread, Thread.State.TIMED_WAITING); 72 73 74 /* 75 *********** park and parkUntil seems not working 76 * ignore this case for now. 77 * Bug ID 5062095 78 *********************************************** 79 80 myThread.goParked(); 81 checkThreadState(myThread, Thread.State.WAITING); 82 83 myThread.goTimedParked(); 84 checkThreadState(myThread, Thread.State.TIMED_WAITING); 85 */ 86 87 88 myThread.goSleeping(); 89 checkThreadState(myThread, Thread.State.TIMED_WAITING); 90 91 myThread.terminate(); 92 checkThreadState(myThread, Thread.State.TERMINATED); 93 94 try { 95 myThread.join(); 96 } catch (InterruptedException e) { 97 e.printStackTrace(); 98 System.out.println("Unexpected exception."); 99 testFailed = true; 100 } 101 102 if (testFailed) 103 throw new RuntimeException("TEST FAILED."); 104 System.out.println("Test passed."); 105 } 106 107 private static void checkThreadState(MyThread t, Thread.State expected) { 108 // wait for the thread to transition to the expected state. 109 // There is a small window between the thread checking the state 110 // and the thread actual entering that state. 111 Thread.State state; 112 int retryCount=0; 113 while ((state = t.getState()) != expected && retryCount < MAX_RETRY) { 114 goSleep(10); 115 retryCount++; 116 } 117 118 if (state == null) { 119 throw new RuntimeException(t.getName() + " expected to have " + 120 expected + " but got null."); 121 } 122 123 if (state != expected) { 124 throw new RuntimeException(String.format("%s expected in %s state but got %s " + 125 "(iterations %d interrupted %d)%n", 126 t.getName(), expected, state, t.iterations, t.interrupted)); 127 } 128 } 129 130 private static void goSleep(long ms) { 131 try { 132 Thread.sleep(ms); 133 } catch (InterruptedException e) { 134 e.printStackTrace(); 135 System.out.println("Unexpected exception."); 136 testFailed = true; 137 } 138 } 139 140 static class MyThread extends Thread { 141 // Phaser to sync between the main thread putting 142 // this thread into various states 143 private Phaser phaser = new Phaser(2); 144 145 MyThread(String name) { 146 super(name); 147 } 148 149 private final int RUNNABLE = 0; 150 private final int BLOCKED = 1; 151 private final int WAITING = 2; 152 private final int TIMED_WAITING = 3; 153 private final int PARKED = 4; 154 private final int TIMED_PARKED = 5; 155 private final int SLEEPING = 6; 156 private final int TERMINATE = 7; 157 158 private volatile int state = RUNNABLE; 159 160 private boolean done = false; 161 volatile int iterations=0; 162 volatile int interrupted=0; 163 public void run() { 164 // Signal main thread to continue. 165 phaser.arriveAndAwaitAdvance(); 166 167 while (!done) { 168 iterations++; 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 interrupted++; 199 } 200 } 201 break; 202 } 203 case TIMED_WAITING: { 204 synchronized (globalLock) { 205 // signal main thread. 206 phaser.arrive(); 207 System.out.println(" myThread is going to timed wait."); 208 try { 209 globalLock.wait(10000); 210 } catch (InterruptedException e) { 211 // ignore 212 interrupted++; 213 } 214 } 215 break; 216 } 217 case PARKED: { 218 // signal main thread. 219 phaser.arrive(); 220 System.out.println(" myThread is going to park."); 221 LockSupport.park(); 222 // give a chance for the main thread to block 223 goSleep(10); 224 break; 225 } 226 case TIMED_PARKED: { 227 // signal main thread. 228 phaser.arrive(); 229 System.out.println(" myThread is going to timed park."); 230 long deadline = System.currentTimeMillis() + 10000*1000; 231 LockSupport.parkUntil(deadline); 232 233 // give a chance for the main thread to block 234 goSleep(10); 235 break; 236 } 237 case SLEEPING: { 238 // signal main thread. 239 phaser.arrive(); 240 System.out.println(" myThread is going to sleep."); 241 try { 242 Thread.sleep(1000000); 243 } catch (InterruptedException e) { 244 // finish sleeping 245 } 246 break; 247 } 248 case TERMINATE: { 249 done = true; 250 // signal main thread. 251 phaser.arrive(); 252 break; 253 } 254 default: 255 break; 256 } 257 } 258 } 259 260 public void waitUntilStarted() { 261 // wait for MyThread. 262 phaser.arriveAndAwaitAdvance(); 263 } 264 265 public void goBlocked() { 266 System.out.println("Waiting myThread to go blocked."); 267 setState(BLOCKED); 268 // wait for MyThread to get to a point just before being blocked 269 phaser.arriveAndAwaitAdvance(); 270 } 271 272 public void goWaiting() { 273 System.out.println("Waiting myThread to go waiting."); 274 setState(WAITING); 275 // wait for MyThread to get to just before wait on object. 276 phaser.arriveAndAwaitAdvance(); 277 } 278 279 public void goTimedWaiting() { 280 System.out.println("Waiting myThread to go timed waiting."); 281 setState(TIMED_WAITING); 282 // wait for MyThread to get to just before timed wait call. 283 phaser.arriveAndAwaitAdvance(); 284 } 285 286 public void goParked() { 287 System.out.println("Waiting myThread to go parked."); 288 setState(PARKED); 289 // wait for MyThread to get to just before parked. 290 phaser.arriveAndAwaitAdvance(); 291 } 292 293 public void goTimedParked() { 294 System.out.println("Waiting myThread to go timed parked."); 295 setState(TIMED_PARKED); 296 // wait for MyThread to get to just before timed park. 297 phaser.arriveAndAwaitAdvance(); 298 } 299 300 public void goSleeping() { 301 System.out.println("Waiting myThread to go sleeping."); 302 setState(SLEEPING); 303 // wait for MyThread to get to just before sleeping 304 phaser.arriveAndAwaitAdvance(); 305 } 306 307 public void terminate() { 308 System.out.println("Waiting myThread to terminate."); 309 setState(TERMINATE); 310 // wait for MyThread to get to just before terminate 311 phaser.arriveAndAwaitAdvance(); 312 } 313 314 private void setState(int newState) { 315 switch (state) { 316 case BLOCKED: 317 while (state == BLOCKED) { 318 goSleep(10); 319 } 320 state = newState; 321 break; 322 case WAITING: 323 case TIMED_WAITING: 324 state = newState; 325 synchronized (globalLock) { 326 globalLock.notify(); 327 } 328 break; 329 case PARKED: 330 case TIMED_PARKED: 331 state = newState; 332 LockSupport.unpark(this); 333 break; 334 case SLEEPING: 335 state = newState; 336 this.interrupt(); 337 break; 338 default: 339 state = newState; 340 break; 341 } 342 iterations=0; 343 interrupted=0; 344 } 345 } 346 }