jdk/test/java/lang/Thread/ThreadStateTest.java
changeset 2 90ce3da70b43
child 5506 202f599c92aa
equal deleted inserted replaced
0:fd16c54261b3 2:90ce3da70b43
       
     1 /*
       
     2  * Copyright 2004 Sun Microsystems, Inc.  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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
       
    20  * CA 95054 USA or visit www.sun.com if you need additional information or
       
    21  * have any 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.Semaphore;
       
    38 
       
    39 public class ThreadStateTest {
       
    40     private static boolean testFailed = false;
       
    41 
       
    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");
       
    52 
       
    53     public static void main(String[] argv) {
       
    54         // Call Thread.getState to force all initialization done
       
    55         // before test verification begins.
       
    56         Thread.currentThread().getState();
       
    57         MyThread myThread = new MyThread("MyThread");
       
    58 
       
    59         // before myThread starts
       
    60         checkThreadState(myThread, Thread.State.NEW);
       
    61 
       
    62         myThread.start();
       
    63         myThread.waitUntilStarted();
       
    64         checkThreadState(myThread, Thread.State.RUNNABLE);
       
    65 
       
    66         synchronized (globalLock) {
       
    67             myThread.goBlocked();
       
    68             checkThreadState(myThread, Thread.State.BLOCKED);
       
    69         }
       
    70 
       
    71         myThread.goWaiting();
       
    72         checkThreadState(myThread, Thread.State.WAITING);
       
    73 
       
    74         myThread.goTimedWaiting();
       
    75         checkThreadState(myThread, Thread.State.TIMED_WAITING);
       
    76 
       
    77 
       
    78       /*
       
    79        *********** park and parkUntil seems not working
       
    80        * ignore this case for now.
       
    81        * Bug ID 5062095
       
    82        ***********************************************
       
    83 
       
    84         myThread.goParked();
       
    85         checkThreadState(myThread, Thread.State.WAITING);
       
    86 
       
    87         myThread.goTimedParked();
       
    88         checkThreadState(myThread, Thread.State.TIMED_WAITING);
       
    89        */
       
    90 
       
    91 
       
    92         myThread.goSleeping();
       
    93         checkThreadState(myThread, Thread.State.TIMED_WAITING);
       
    94 
       
    95         myThread.terminate();
       
    96         checkThreadState(myThread, Thread.State.TERMINATED);
       
    97 
       
    98         try {
       
    99             myThread.join();
       
   100         } catch (InterruptedException e) {
       
   101             e.printStackTrace();
       
   102             System.out.println("Unexpected exception.");
       
   103             testFailed = true;
       
   104         }
       
   105         if (testFailed)
       
   106             throw new RuntimeException("TEST FAILED.");
       
   107         System.out.println("Test passed.");
       
   108     }
       
   109 
       
   110     private static void checkThreadState(Thread t, Thread.State expected) {
       
   111         Thread.State state = t.getState();
       
   112         System.out.println("Checking thread state " + state);
       
   113         if (state == null) {
       
   114             throw new RuntimeException(t.getName() + " expected to have " +
       
   115                 expected + " but got null.");
       
   116         }
       
   117 
       
   118         if (state != expected) {
       
   119             throw new RuntimeException(t.getName() + " expected to have " +
       
   120                 expected + " but got " + state);
       
   121         }
       
   122     }
       
   123 
       
   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     private static void goSleep(long ms) {
       
   132         try {
       
   133             Thread.sleep(ms);
       
   134         } catch (InterruptedException e) {
       
   135             e.printStackTrace();
       
   136             System.out.println("Unexpected exception.");
       
   137             testFailed = true;
       
   138         }
       
   139     }
       
   140 
       
   141     static class MyThread extends Thread {
       
   142         private ThreadExecutionSynchronizer thrsync = new ThreadExecutionSynchronizer();
       
   143 
       
   144         MyThread(String name) {
       
   145             super(name);
       
   146         }
       
   147 
       
   148         private final int RUNNABLE = 0;
       
   149         private final int BLOCKED = 1;
       
   150         private final int WAITING = 2;
       
   151         private final int TIMED_WAITING = 3;
       
   152         private final int PARKED = 4;
       
   153         private final int TIMED_PARKED = 5;
       
   154         private final int SLEEPING = 6;
       
   155         private final int TERMINATE = 7;
       
   156         private int state = RUNNABLE;
       
   157 
       
   158         private boolean done = false;
       
   159         public void run() {
       
   160             // Signal main thread to continue.
       
   161             thrsync.signal();
       
   162             while (!done) {
       
   163                 switch (state) {
       
   164                     case RUNNABLE: {
       
   165                         double sum = 0;
       
   166                         for (int i = 0; i < 1000; i++) {
       
   167                            double r = Math.random();
       
   168                            double x = Math.pow(3, r);
       
   169                            sum += x - r;
       
   170                         }
       
   171                         break;
       
   172                     }
       
   173                     case BLOCKED: {
       
   174                         // signal main thread.
       
   175                         thrsync.signal();
       
   176                         System.out.println("  myThread is going to block.");
       
   177                         synchronized (globalLock) {
       
   178                             // finish blocking
       
   179                             state = RUNNABLE;
       
   180                         }
       
   181                         break;
       
   182                     }
       
   183                     case WAITING: {
       
   184                         synchronized (globalLock) {
       
   185                             // signal main thread.
       
   186                             thrsync.signal();
       
   187                             System.out.println("  myThread is going to wait.");
       
   188                             try {
       
   189                                 globalLock.wait();
       
   190                             } catch (InterruptedException e) {
       
   191                                 // ignore
       
   192                             }
       
   193                         }
       
   194                         break;
       
   195                     }
       
   196                     case TIMED_WAITING: {
       
   197                         synchronized (globalLock) {
       
   198                             // signal main thread.
       
   199                             thrsync.signal();
       
   200                             System.out.println("  myThread is going to timed wait.");
       
   201                             try {
       
   202                                 globalLock.wait(10000);
       
   203                             } catch (InterruptedException e) {
       
   204                                 // ignore
       
   205                             }
       
   206                         }
       
   207                         break;
       
   208                     }
       
   209                     case PARKED: {
       
   210                         // signal main thread.
       
   211                         thrsync.signal();
       
   212                         System.out.println("  myThread is going to park.");
       
   213                         LockSupport.park();
       
   214                         // give a chance for the main thread to block
       
   215                         goSleep(10);
       
   216                         break;
       
   217                     }
       
   218                     case TIMED_PARKED: {
       
   219                         // signal main thread.
       
   220                         thrsync.signal();
       
   221                         System.out.println("  myThread is going to timed park.");
       
   222                         long deadline = System.currentTimeMillis() + 10000*1000;
       
   223                         LockSupport.parkUntil(deadline);
       
   224 
       
   225                         // give a chance for the main thread to block
       
   226                         goSleep(10);
       
   227                         break;
       
   228                     }
       
   229                     case SLEEPING: {
       
   230                         // signal main thread.
       
   231                         thrsync.signal();
       
   232                         System.out.println("  myThread is going to sleep.");
       
   233                         try {
       
   234                             Thread.sleep(1000000);
       
   235                         } catch (InterruptedException e) {
       
   236                             // finish sleeping
       
   237                             interrupted();
       
   238                         }
       
   239                         break;
       
   240                     }
       
   241                     case TERMINATE: {
       
   242                         done = true;
       
   243                         // signal main thread.
       
   244                         thrsync.signal();
       
   245                         break;
       
   246                     }
       
   247                     default:
       
   248                         break;
       
   249                 }
       
   250             }
       
   251         }
       
   252         public void waitUntilStarted() {
       
   253             // wait for MyThread.
       
   254             thrsync.waitForSignal();
       
   255             goSleep(10);
       
   256         }
       
   257 
       
   258         public void goBlocked() {
       
   259             System.out.println("Waiting myThread to go blocked.");
       
   260             setState(BLOCKED);
       
   261             // wait for MyThread to get blocked
       
   262             thrsync.waitForSignal();
       
   263             goSleep(20);
       
   264         }
       
   265 
       
   266         public void goWaiting() {
       
   267             System.out.println("Waiting myThread to go waiting.");
       
   268             setState(WAITING);
       
   269             // wait for  MyThread to wait on object.
       
   270             thrsync.waitForSignal();
       
   271             goSleep(20);
       
   272         }
       
   273         public void goTimedWaiting() {
       
   274             System.out.println("Waiting myThread to go timed waiting.");
       
   275             setState(TIMED_WAITING);
       
   276             // wait for MyThread timed wait call.
       
   277             thrsync.waitForSignal();
       
   278             goSleep(20);
       
   279         }
       
   280         public void goParked() {
       
   281             System.out.println("Waiting myThread to go parked.");
       
   282             setState(PARKED);
       
   283             // wait for  MyThread state change to PARKED.
       
   284             thrsync.waitForSignal();
       
   285             goSleep(20);
       
   286         }
       
   287         public void goTimedParked() {
       
   288             System.out.println("Waiting myThread to go timed parked.");
       
   289             setState(TIMED_PARKED);
       
   290             // wait for  MyThread.
       
   291             thrsync.waitForSignal();
       
   292             goSleep(20);
       
   293         }
       
   294 
       
   295         public void goSleeping() {
       
   296             System.out.println("Waiting myThread to go sleeping.");
       
   297             setState(SLEEPING);
       
   298             // wait for  MyThread.
       
   299             thrsync.waitForSignal();
       
   300             goSleep(20);
       
   301         }
       
   302         public void terminate() {
       
   303             System.out.println("Waiting myThread to terminate.");
       
   304             setState(TERMINATE);
       
   305             // wait for  MyThread.
       
   306             thrsync.waitForSignal();
       
   307             goSleep(20);
       
   308         }
       
   309 
       
   310         private void setState(int newState) {
       
   311             switch (state) {
       
   312                 case BLOCKED:
       
   313                     while (state == BLOCKED) {
       
   314                         goSleep(20);
       
   315                     }
       
   316                     state = newState;
       
   317                     break;
       
   318                 case WAITING:
       
   319                 case TIMED_WAITING:
       
   320                     state = newState;
       
   321                     synchronized (globalLock) {
       
   322                         globalLock.notify();
       
   323                     }
       
   324                     break;
       
   325                 case PARKED:
       
   326                 case TIMED_PARKED:
       
   327                     state = newState;
       
   328                     LockSupport.unpark(this);
       
   329                     break;
       
   330                 case SLEEPING:
       
   331                     state = newState;
       
   332                     this.interrupt();
       
   333                     break;
       
   334                 default:
       
   335                     state = newState;
       
   336                     break;
       
   337             }
       
   338         }
       
   339     }
       
   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 }