--- old/test/java/lang/Thread/ThreadStateTest.java Tue Jun 21 13:41:13 2011 +++ new/test/java/lang/Thread/ThreadStateTest.java Tue Jun 21 13:41:13 2011 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2004, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -34,21 +34,16 @@ */ import java.util.concurrent.locks.LockSupport; -import java.util.concurrent.Semaphore; +import java.util.concurrent.Phaser; public class ThreadStateTest { + // maximum number of retries when checking for thread state. + static final int MAX_RETRY = 500; + private static boolean testFailed = false; - static class Lock { - private String name; - Lock(String name) { - this.name = name; - } - public String toString() { - return name; - } - } - private static Lock globalLock = new Lock("my lock"); + // used to achieve waiting states + static final Object globalLock = new Object(); public static void main(String[] argv) { // Call Thread.getState to force all initialization done @@ -93,8 +88,6 @@ checkThreadState(myThread, Thread.State.TIMED_WAITING); myThread.terminate(); - checkThreadState(myThread, Thread.State.TERMINATED); - try { myThread.join(); } catch (InterruptedException e) { @@ -102,6 +95,9 @@ System.out.println("Unexpected exception."); testFailed = true; } + checkThreadState(myThread, Thread.State.TERMINATED); + + if (testFailed) throw new RuntimeException("TEST FAILED."); System.out.println("Test passed."); @@ -108,7 +104,20 @@ } private static void checkThreadState(Thread t, Thread.State expected) { - Thread.State state = t.getState(); + // wait for the thread to transition to the expected state. + // There is a small window between the thread checking the state + // and the thread actual entering that state. + Thread.State state; + int retryCount=0; + while ((state = t.getState()) != expected && retryCount < MAX_RETRY) { + if (state != Thread.State.RUNNABLE) { + throw new RuntimeException("Thread not in expected state yet," + + " but it should at least be RUNNABLE"); + } + goSleep(10); + retryCount++; + } + System.out.println("Checking thread state " + state); if (state == null) { throw new RuntimeException(t.getName() + " expected to have " + @@ -121,13 +130,6 @@ } } - private static String getLockName(Object lock) { - if (lock == null) return null; - - return lock.getClass().getName() + '@' + - Integer.toHexString(System.identityHashCode(lock)); - } - private static void goSleep(long ms) { try { Thread.sleep(ms); @@ -139,7 +141,9 @@ } static class MyThread extends Thread { - private ThreadExecutionSynchronizer thrsync = new ThreadExecutionSynchronizer(); + // Phaser to sync between the main thread putting + // this thread into various states + private Phaser phaser = new Phaser(2); MyThread(String name) { super(name); @@ -153,12 +157,14 @@ private final int TIMED_PARKED = 5; private final int SLEEPING = 6; private final int TERMINATE = 7; - private int state = RUNNABLE; + + private volatile int state = RUNNABLE; private boolean done = false; public void run() { // Signal main thread to continue. - thrsync.signal(); + phaser.arriveAndAwaitAdvance(); + while (!done) { switch (state) { case RUNNABLE: { @@ -172,7 +178,7 @@ } case BLOCKED: { // signal main thread. - thrsync.signal(); + phaser.arrive(); System.out.println(" myThread is going to block."); synchronized (globalLock) { // finish blocking @@ -183,7 +189,7 @@ case WAITING: { synchronized (globalLock) { // signal main thread. - thrsync.signal(); + phaser.arrive(); System.out.println(" myThread is going to wait."); try { globalLock.wait(); @@ -196,7 +202,7 @@ case TIMED_WAITING: { synchronized (globalLock) { // signal main thread. - thrsync.signal(); + phaser.arrive(); System.out.println(" myThread is going to timed wait."); try { globalLock.wait(10000); @@ -208,7 +214,7 @@ } case PARKED: { // signal main thread. - thrsync.signal(); + phaser.arrive(); System.out.println(" myThread is going to park."); LockSupport.park(); // give a chance for the main thread to block @@ -217,7 +223,7 @@ } case TIMED_PARKED: { // signal main thread. - thrsync.signal(); + phaser.arrive(); System.out.println(" myThread is going to timed park."); long deadline = System.currentTimeMillis() + 10000*1000; LockSupport.parkUntil(deadline); @@ -228,7 +234,7 @@ } case SLEEPING: { // signal main thread. - thrsync.signal(); + phaser.arrive(); System.out.println(" myThread is going to sleep."); try { Thread.sleep(1000000); @@ -240,8 +246,6 @@ } case TERMINATE: { done = true; - // signal main thread. - thrsync.signal(); break; } default: @@ -249,62 +253,57 @@ } } } + public void waitUntilStarted() { // wait for MyThread. - thrsync.waitForSignal(); - goSleep(10); + phaser.arriveAndAwaitAdvance(); } public void goBlocked() { System.out.println("Waiting myThread to go blocked."); setState(BLOCKED); - // wait for MyThread to get blocked - thrsync.waitForSignal(); - goSleep(20); + // wait for MyThread to get to a point just before being blocked + phaser.arriveAndAwaitAdvance(); } public void goWaiting() { System.out.println("Waiting myThread to go waiting."); setState(WAITING); - // wait for MyThread to wait on object. - thrsync.waitForSignal(); - goSleep(20); + // wait for MyThread to get to just before wait on object. + phaser.arriveAndAwaitAdvance(); } + public void goTimedWaiting() { System.out.println("Waiting myThread to go timed waiting."); setState(TIMED_WAITING); - // wait for MyThread timed wait call. - thrsync.waitForSignal(); - goSleep(20); + // wait for MyThread to get to just before timed wait call. + phaser.arriveAndAwaitAdvance(); } + public void goParked() { System.out.println("Waiting myThread to go parked."); setState(PARKED); - // wait for MyThread state change to PARKED. - thrsync.waitForSignal(); - goSleep(20); + // wait for MyThread to get to just before parked. + phaser.arriveAndAwaitAdvance(); } + public void goTimedParked() { System.out.println("Waiting myThread to go timed parked."); setState(TIMED_PARKED); - // wait for MyThread. - thrsync.waitForSignal(); - goSleep(20); + // wait for MyThread to get to just before timed park. + phaser.arriveAndAwaitAdvance(); } public void goSleeping() { System.out.println("Waiting myThread to go sleeping."); setState(SLEEPING); - // wait for MyThread. - thrsync.waitForSignal(); - goSleep(20); + // wait for MyThread to get to just before sleeping + phaser.arriveAndAwaitAdvance(); } + public void terminate() { System.out.println("Waiting myThread to terminate."); setState(TERMINATE); - // wait for MyThread. - thrsync.waitForSignal(); - goSleep(20); } private void setState(int newState) { @@ -337,50 +336,4 @@ } } } - - - - static class ThreadExecutionSynchronizer { - - private boolean waiting; - private Semaphore semaphore; - - public ThreadExecutionSynchronizer() { - semaphore = new Semaphore(1); - waiting = false; - } - - // Synchronizes two threads execution points. - // Basically any thread could get scheduled to run and - // it is not possible to know which thread reaches expected - // execution point. So whichever thread reaches a execution - // point first wait for the second thread. When the second thread - // reaches the expected execution point will wake up - // the thread which is waiting here. - void stopOrGo() { - semaphore.acquireUninterruptibly(); // Thread can get blocked. - if (!waiting) { - waiting = true; - // Wait for second thread to enter this method. - while(!semaphore.hasQueuedThreads()) { - try { - Thread.sleep(20); - } catch (InterruptedException xx) {} - } - semaphore.release(); - } else { - waiting = false; - semaphore.release(); - } - } - - // Wrapper function just for code readability. - void waitForSignal() { - stopOrGo(); - } - - void signal() { - stopOrGo(); - } - } } --- old/test/ProblemList.txt Tue Jun 21 13:41:14 2011 +++ new/test/ProblemList.txt Tue Jun 21 13:41:14 2011 @@ -207,9 +207,6 @@ # Times out on solaris sparc -server java/lang/ThreadLocal/MemoryLeak.java solaris-all -# Windows X64, RuntimeException: MyThread expected to have RUNNABLE but got WAITING -java/lang/Thread/ThreadStateTest.java generic-all - ############################################################################ # jdk_management