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 }