0N/A/*
2362N/A * Copyright (c) 2004, 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/*
0N/A *
0N/A * Sample target application for jvmti demos
0N/A *
0N/A * java Context [threadCount [iterationCount [sleepContention]]]
0N/A * Default: java Context 5 10 0
0N/A *
0N/A * threadCount Number of threads
0N/A * iterationCount Total turns taken for all threads
0N/A * sleepContention Time for main thread to sleep while holding lock
0N/A * (creates monitor contention on all other threads)
0N/A *
0N/A */
0N/A
0N/A/* Used to sync up turns and keep track of who's turn it is */
0N/Afinal class TurnChecker {
0N/A int thread_index;
0N/A TurnChecker(int thread_index) {
0N/A this.thread_index = thread_index;
0N/A }
0N/A}
0N/A
0N/A/* Creates a bunch of threads that sequentially take turns */
0N/Apublic final class Context extends Thread {
0N/A /* Used to track threads */
0N/A private static long startTime;
0N/A private static TurnChecker turn = new TurnChecker(-1);
0N/A private static int total_turns_taken;
0N/A
0N/A /* Used for each Context thread */
0N/A private final int thread_count;
0N/A private final int thread_index;
0N/A private final int thread_turns;
0N/A
0N/A /* Main program */
0N/A public static void main(String[] argv) throws InterruptedException {
0N/A int default_thread_count = 5;
0N/A int default_thread_turns = 10;
0N/A int default_contention_sleep = 0;
0N/A int expected_turns_taken;
0N/A long sleepTime = 10L;
0N/A
0N/A /* Override defaults */
0N/A if ( argv.length >= 1 ) {
0N/A default_thread_count = Integer.parseInt(argv[0]);
0N/A }
0N/A if ( argv.length >= 2 ) {
0N/A expected_turns_taken = Integer.parseInt(argv[1]);
0N/A default_thread_turns = expected_turns_taken/default_thread_count;
0N/A }
0N/A expected_turns_taken = default_thread_count*default_thread_turns;
0N/A if ( argv.length >= 3 ) {
0N/A default_contention_sleep = Integer.parseInt(argv[2]);
0N/A }
0N/A
0N/A System.out.println("Context started with "
0N/A + default_thread_count + " threads and "
0N/A + default_thread_turns + " turns per thread");
0N/A
0N/A /* Get all threads running (they will block until we set turn) */
0N/A for (int i = 0; i < default_thread_count; i++) {
0N/A new Context(default_thread_count, i, default_thread_turns).start();
0N/A }
0N/A
0N/A /* Sleep to make sure thread_index 0 make it to the wait call */
0N/A System.out.println("Context sleeping, so threads will start wait");
0N/A Thread.yield();
0N/A Thread.sleep(sleepTime);
0N/A
0N/A /* Save start time */
0N/A startTime = System.currentTimeMillis();
0N/A
0N/A /* This triggers the starting of taking turns */
0N/A synchronized (turn) {
0N/A turn.thread_index = 0;
0N/A turn.notifyAll();
0N/A }
0N/A System.out.println("Context sleeping, so threads can run");
0N/A Thread.yield();
0N/A Thread.sleep(sleepTime);
0N/A
0N/A /* Wait for threads to finish (after everyone has had their turns) */
0N/A while ( true ) {
0N/A boolean done;
0N/A done = false;
0N/A synchronized (turn) {
0N/A if ( total_turns_taken == expected_turns_taken ) {
0N/A done = true;
0N/A }
0N/A /* Create some monitor contention by sleeping with lock */
0N/A if ( default_contention_sleep > 0 ) {
0N/A System.out.println("Context sleeping, to create contention");
0N/A Thread.yield();
0N/A Thread.sleep((long)default_contention_sleep);
0N/A }
0N/A }
0N/A if ( done )
0N/A break;
0N/A System.out.println("Context sleeping, so threads will complete");
0N/A Thread.sleep(sleepTime);
0N/A }
0N/A
0N/A long endTime = System.currentTimeMillis();
0N/A long totalTime = endTime - startTime;
0N/A
0N/A System.out.println("Total time (milliseconds): " + totalTime);
0N/A System.out.println("Milliseconds per thread: " +
0N/A ((double)totalTime / (default_thread_count)));
0N/A
0N/A System.out.println("Context completed");
0N/A System.exit(0);
0N/A }
0N/A
0N/A /* Thread object to run */
0N/A Context(int thread_count, int thread_index, int thread_turns) {
0N/A this.thread_count = thread_count;
0N/A this.thread_index = thread_index;
0N/A this.thread_turns = thread_turns;
0N/A }
0N/A
0N/A /* Main for thread */
0N/A public void run() {
0N/A int next_thread_index = (thread_index + 1) % thread_count;
0N/A int turns_taken = 0;
0N/A
0N/A try {
0N/A
0N/A /* Loop until we make sure we get all our turns */
0N/A for (int i = 0; i < thread_turns * thread_count; i++) {
0N/A synchronized (turn) {
0N/A /* Keep waiting for our turn */
0N/A while (turn.thread_index != thread_index)
0N/A turn.wait();
0N/A /* MY TURN! Each thread gets thread_turns */
0N/A total_turns_taken++;
0N/A turns_taken++;
0N/A System.out.println("Turn #" + total_turns_taken
0N/A + " taken by thread " + thread_index
0N/A + ", " + turns_taken
0N/A + " turns taken by this thread");
0N/A /* Give next thread a turn */
0N/A turn.thread_index = next_thread_index;
0N/A turn.notifyAll();
0N/A }
0N/A /* If we've had all our turns, break out of this loop */
0N/A if ( thread_turns == turns_taken ) {
0N/A break;
0N/A }
0N/A }
0N/A } catch (InterruptedException intEx) { /* skip */ }
0N/A
0N/A /* Make sure we got all our turns */
0N/A if ( thread_turns != turns_taken ) {
0N/A System.out.println("ERROR: thread got " + turns_taken
0N/A + " turns, expected " + thread_turns);
0N/A System.exit(1);
0N/A }
0N/A }
0N/A}