0N/A/*
2362N/A * Copyright (c) 2003, 2006, Oracle and/or its affiliates. All rights reserved.
0N/A * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
0N/A *
0N/A * This code is free software; you can redistribute it and/or modify it
0N/A * under the terms of the GNU General Public License version 2 only, as
0N/A * published by the Free Software Foundation.
0N/A *
0N/A * This code is distributed in the hope that it will be useful, but WITHOUT
0N/A * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
0N/A * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
0N/A * version 2 for more details (a copy is included in the LICENSE file that
0N/A * accompanied this code).
0N/A *
0N/A * You should have received a copy of the GNU General Public License version
0N/A * 2 along with this work; if not, write to the Free Software Foundation,
0N/A * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
0N/A *
2362N/A * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
2362N/A * or visit www.oracle.com if you need additional information or have any
2362N/A * questions.
0N/A */
0N/A
0N/A/*
0N/A * @test
1153N/A * @bug 4967283 5080203
0N/A * @summary Basic unit test of thread states returned by
0N/A * ThreadMXBean.getThreadInfo.getThreadState().
0N/A * It also tests lock information returned by ThreadInfo.
0N/A *
0N/A * @author Mandy Chung
0N/A *
1256N/A * @build ThreadExecutionSynchronizer Utils
0N/A * @run main ThreadStateTest
0N/A */
0N/A
0N/Aimport java.lang.management.ManagementFactory;
0N/Aimport java.lang.management.ThreadMXBean;
0N/Aimport java.lang.management.ThreadInfo;
0N/A
0N/Aimport java.util.concurrent.locks.LockSupport;
0N/A
0N/Apublic class ThreadStateTest {
0N/A private static final ThreadMXBean tm = ManagementFactory.getThreadMXBean();
0N/A
0N/A static class Lock {
0N/A private String name;
0N/A Lock(String name) {
0N/A this.name = name;
0N/A }
0N/A public String toString() {
0N/A return name;
0N/A }
0N/A }
0N/A private static Lock globalLock = new Lock("my lock");
0N/A
0N/A public static void main(String[] argv) {
0N/A // Force thread state initialization now before the test
0N/A // verification begins.
0N/A Thread.currentThread().getState();
0N/A
0N/A MyThread myThread = new MyThread("MyThread");
0N/A
0N/A // before myThread starts
1256N/A // Utils.checkThreadState(myThread, Thread.State.NEW);
0N/A
0N/A myThread.start();
0N/A myThread.waitUntilStarted();
1256N/A Utils.checkThreadState(myThread, Thread.State.RUNNABLE);
0N/A checkLockInfo(myThread, Thread.State.RUNNABLE, null, null);
0N/A
0N/A myThread.suspend();
1256N/A Utils.goSleep(10);
0N/A checkSuspendedThreadState(myThread, Thread.State.RUNNABLE);
0N/A myThread.resume();
0N/A
0N/A synchronized (globalLock) {
0N/A myThread.goBlocked();
1256N/A Utils.checkThreadState(myThread, Thread.State.BLOCKED);
0N/A checkLockInfo(myThread, Thread.State.BLOCKED,
0N/A globalLock, Thread.currentThread());
0N/A }
0N/A
0N/A myThread.goWaiting();
1256N/A Utils.checkThreadState(myThread, Thread.State.WAITING);
0N/A checkLockInfo(myThread, Thread.State.WAITING,
0N/A globalLock, null);
0N/A
0N/A myThread.goTimedWaiting();
1256N/A Utils.checkThreadState(myThread, Thread.State.TIMED_WAITING);
0N/A checkLockInfo(myThread, Thread.State.TIMED_WAITING,
0N/A globalLock, null);
0N/A
0N/A
0N/A
0N/A /*
0N/A *********** parkUntil seems not working
0N/A * ignore this park case for now.
0N/A
0N/A Bug ID : 5062095
0N/A ***********************************************
0N/A myThread.goParked();
1256N/A Utils.checkThreadState(myThread, Thread.State.WAITING);
0N/A checkLockInfo(myThread, Thread.State.WAITING, null, null);
0N/A
0N/A myThread.goTimedParked();
1256N/A Utils.checkThreadState(myThread, Thread.State.TIMED_WAITING);
0N/A checkLockInfo(myThread, Thread.State.TIMED_WAITING, null, null);
0N/A
0N/A */
0N/A
0N/A myThread.goSleeping();
1256N/A Utils.checkThreadState(myThread, Thread.State.TIMED_WAITING);
0N/A checkLockInfo(myThread, Thread.State.TIMED_WAITING, null, null);
0N/A
0N/A
0N/A myThread.terminate();
1256N/A // Utils.checkThreadState(myThread, ThreadState.TERMINATED);
0N/A
0N/A try {
0N/A myThread.join();
0N/A } catch (InterruptedException e) {
0N/A e.printStackTrace();
1256N/A System.out.println("TEST FAILED: Unexpected exception.");
1256N/A throw new RuntimeException(e);
0N/A }
0N/A System.out.println("Test passed.");
0N/A }
0N/A
0N/A private static void checkSuspendedThreadState(Thread t, Thread.State state) {
0N/A ThreadInfo info = tm.getThreadInfo(t.getId());
0N/A if (info == null) {
0N/A throw new RuntimeException(t.getName() +
0N/A " expected to have ThreadInfo " +
0N/A " but got null.");
0N/A }
0N/A
0N/A if (info.getThreadState() != state) {
0N/A throw new RuntimeException(t.getName() + " expected to be in " +
0N/A state + " state but got " + info.getThreadState());
0N/A }
0N/A
0N/A if (!info.isSuspended()) {
0N/A throw new RuntimeException(t.getName() + " expected to be suspended " +
0N/A " but isSuspended() returns " + info.isSuspended());
0N/A }
1256N/A Utils.checkThreadState(t, state);
0N/A }
0N/A
0N/A private static String getLockName(Object lock) {
0N/A if (lock == null) return null;
0N/A
0N/A return lock.getClass().getName() + '@' +
0N/A Integer.toHexString(System.identityHashCode(lock));
0N/A }
0N/A
0N/A private static void checkLockInfo(Thread t, Thread.State state, Object lock, Thread owner) {
0N/A ThreadInfo info = tm.getThreadInfo(t.getId());
0N/A if (info == null) {
0N/A throw new RuntimeException(t.getName() +
0N/A " expected to have ThreadInfo " +
0N/A " but got null.");
0N/A }
0N/A
0N/A if (info.getThreadState() != state) {
0N/A throw new RuntimeException(t.getName() + " expected to be in " +
0N/A state + " state but got " + info.getThreadState());
0N/A }
0N/A
0N/A if (lock == null && info.getLockName() != null) {
0N/A throw new RuntimeException(t.getName() +
0N/A " expected not to be blocked on any lock" +
0N/A " but got " + info.getLockName());
0N/A }
0N/A String expectedLockName = getLockName(lock);
0N/A if (lock != null && info.getLockName() == null) {
0N/A throw new RuntimeException(t.getName() +
0N/A " expected to be blocked on lock [" + expectedLockName +
0N/A "] but got null.");
0N/A }
0N/A
0N/A if (lock != null && !expectedLockName.equals(info.getLockName())) {
0N/A throw new RuntimeException(t.getName() +
0N/A " expected to be blocked on lock [" + expectedLockName +
0N/A "] but got [" + info.getLockName() + "].");
0N/A }
0N/A
0N/A if (owner == null && info.getLockOwnerName() != null) {
0N/A throw new RuntimeException("Lock owner is expected " +
0N/A " to be null but got " + info.getLockOwnerName());
0N/A }
0N/A
0N/A if (owner != null && info.getLockOwnerName() == null) {
0N/A throw new RuntimeException("Lock owner is expected to be " +
0N/A owner.getName() +
0N/A " but got null.");
0N/A }
0N/A if (owner != null && !info.getLockOwnerName().equals(owner.getName())) {
0N/A throw new RuntimeException("Lock owner is expected to be " +
0N/A owner.getName() +
0N/A " but got " + owner.getName());
0N/A }
0N/A if (owner == null && info.getLockOwnerId() != -1) {
0N/A throw new RuntimeException("Lock owner is expected " +
0N/A " to be -1 but got " + info.getLockOwnerId());
0N/A }
0N/A
0N/A if (owner != null && info.getLockOwnerId() <= 0) {
0N/A throw new RuntimeException("Lock owner is expected to be " +
0N/A owner.getName() + "(id = " + owner.getId() +
0N/A ") but got " + info.getLockOwnerId());
0N/A }
0N/A if (owner != null && info.getLockOwnerId() != owner.getId()) {
0N/A throw new RuntimeException("Lock owner is expected to be " +
0N/A owner.getName() + "(id = " + owner.getId() +
0N/A ") but got " + info.getLockOwnerId());
0N/A }
0N/A if (info.isSuspended()) {
0N/A throw new RuntimeException(t.getName() +
0N/A " isSuspended() returns " + info.isSuspended());
0N/A }
0N/A }
0N/A
0N/A static class MyThread extends Thread {
0N/A private ThreadExecutionSynchronizer thrsync = new ThreadExecutionSynchronizer();
0N/A
0N/A MyThread(String name) {
0N/A super(name);
0N/A }
0N/A
0N/A private final int RUNNABLE = 0;
0N/A private final int BLOCKED = 1;
0N/A private final int WAITING = 2;
0N/A private final int TIMED_WAITING = 3;
0N/A private final int PARKED = 4;
0N/A private final int TIMED_PARKED = 5;
0N/A private final int SLEEPING = 6;
0N/A private final int TERMINATE = 7;
0N/A private int state = RUNNABLE;
0N/A
0N/A private boolean done = false;
0N/A public void run() {
0N/A // Signal main thread to continue.
0N/A thrsync.signal();
0N/A while (!done) {
0N/A switch (state) {
0N/A case RUNNABLE: {
0N/A double sum = 0;
0N/A for (int i = 0; i < 1000; i++) {
0N/A double r = Math.random();
0N/A double x = Math.pow(3, r);
0N/A sum += x - r;
0N/A }
0N/A break;
0N/A }
0N/A case BLOCKED: {
0N/A // signal main thread.
0N/A thrsync.signal();
0N/A System.out.println(" myThread is going to block.");
0N/A synchronized (globalLock) {
0N/A // finish blocking
0N/A state = RUNNABLE;
0N/A }
0N/A break;
0N/A }
0N/A case WAITING: {
0N/A synchronized (globalLock) {
0N/A // signal main thread.
0N/A thrsync.signal();
0N/A System.out.println(" myThread is going to wait.");
0N/A try {
0N/A globalLock.wait();
0N/A } catch (InterruptedException e) {
0N/A // ignore
0N/A }
0N/A }
0N/A break;
0N/A }
0N/A case TIMED_WAITING: {
0N/A synchronized (globalLock) {
0N/A // signal main thread.
0N/A thrsync.signal();
0N/A System.out.println(" myThread is going to timed wait.");
0N/A try {
0N/A globalLock.wait(10000);
0N/A } catch (InterruptedException e) {
0N/A // ignore
0N/A }
0N/A }
0N/A break;
0N/A }
0N/A case PARKED: {
0N/A // signal main thread.
0N/A thrsync.signal();
0N/A System.out.println(" myThread is going to park.");
0N/A LockSupport.park();
0N/A // give a chance for the main thread to block
0N/A System.out.println(" myThread is going to park.");
1256N/A Utils.goSleep(10);
0N/A break;
0N/A }
0N/A case TIMED_PARKED: {
0N/A // signal main thread.
0N/A thrsync.signal();
0N/A System.out.println(" myThread is going to timed park.");
0N/A long deadline = System.currentTimeMillis() + 10000*1000;
0N/A LockSupport.parkUntil(deadline);
0N/A
0N/A // give a chance for the main thread to block
1256N/A Utils.goSleep(10);
0N/A break;
0N/A }
0N/A case SLEEPING: {
0N/A // signal main thread.
0N/A thrsync.signal();
0N/A System.out.println(" myThread is going to sleep.");
0N/A try {
0N/A Thread.sleep(1000000);
0N/A } catch (InterruptedException e) {
0N/A // finish sleeping
0N/A interrupted();
0N/A }
0N/A break;
0N/A }
0N/A case TERMINATE: {
0N/A done = true;
0N/A // signal main thread.
0N/A thrsync.signal();
0N/A break;
0N/A }
0N/A default:
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A public void waitUntilStarted() {
0N/A // wait for MyThread.
0N/A thrsync.waitForSignal();
1256N/A Utils.goSleep(10);
0N/A }
0N/A
0N/A public void goBlocked() {
0N/A System.out.println("Waiting myThread to go blocked.");
0N/A setState(BLOCKED);
0N/A // wait for MyThread to get blocked
0N/A thrsync.waitForSignal();
1256N/A Utils.goSleep(20);
0N/A }
0N/A
0N/A public void goWaiting() {
0N/A System.out.println("Waiting myThread to go waiting.");
0N/A setState(WAITING);
0N/A // wait for MyThread to wait on object.
0N/A thrsync.waitForSignal();
1256N/A Utils.goSleep(20);
0N/A }
0N/A public void goTimedWaiting() {
0N/A System.out.println("Waiting myThread to go timed waiting.");
0N/A setState(TIMED_WAITING);
0N/A // wait for MyThread timed wait call.
0N/A thrsync.waitForSignal();
1256N/A Utils.goSleep(20);
0N/A }
0N/A public void goParked() {
0N/A System.out.println("Waiting myThread to go parked.");
0N/A setState(PARKED);
0N/A // wait for MyThread state change to PARKED.
0N/A thrsync.waitForSignal();
1256N/A Utils.goSleep(20);
0N/A }
0N/A public void goTimedParked() {
0N/A System.out.println("Waiting myThread to go timed parked.");
0N/A setState(TIMED_PARKED);
0N/A // wait for MyThread.
0N/A thrsync.waitForSignal();
1256N/A Utils.goSleep(20);
0N/A }
0N/A
0N/A public void goSleeping() {
0N/A System.out.println("Waiting myThread to go sleeping.");
0N/A setState(SLEEPING);
0N/A // wait for MyThread.
0N/A thrsync.waitForSignal();
1256N/A Utils.goSleep(20);
0N/A }
0N/A public void terminate() {
0N/A System.out.println("Waiting myThread to terminate.");
0N/A setState(TERMINATE);
0N/A // wait for MyThread.
0N/A thrsync.waitForSignal();
1256N/A Utils.goSleep(20);
0N/A }
0N/A
0N/A private void setState(int newState) {
0N/A switch (state) {
0N/A case BLOCKED:
0N/A while (state == BLOCKED) {
1256N/A Utils.goSleep(20);
0N/A }
0N/A state = newState;
0N/A break;
0N/A case WAITING:
0N/A case TIMED_WAITING:
0N/A state = newState;
0N/A synchronized (globalLock) {
0N/A globalLock.notify();
0N/A }
0N/A break;
0N/A case PARKED:
0N/A case TIMED_PARKED:
0N/A state = newState;
0N/A LockSupport.unpark(this);
0N/A break;
0N/A case SLEEPING:
0N/A state = newState;
0N/A this.interrupt();
0N/A break;
0N/A default:
0N/A state = newState;
0N/A break;
0N/A }
0N/A }
0N/A }
0N/A}