2
+ − 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
/*
+ − 26
*
+ − 27
* Sample target application for jvmti demos
+ − 28
*
+ − 29
* java Context [threadCount [iterationCount [sleepContention]]]
+ − 30
* Default: java Context 5 10 0
+ − 31
*
+ − 32
* threadCount Number of threads
+ − 33
* iterationCount Total turns taken for all threads
+ − 34
* sleepContention Time for main thread to sleep while holding lock
+ − 35
* (creates monitor contention on all other threads)
+ − 36
*
+ − 37
*/
+ − 38
+ − 39
/* Used to sync up turns and keep track of who's turn it is */
+ − 40
final class TurnChecker {
+ − 41
int thread_index;
+ − 42
TurnChecker(int thread_index) {
+ − 43
this.thread_index = thread_index;
+ − 44
}
+ − 45
}
+ − 46
+ − 47
/* Creates a bunch of threads that sequentially take turns */
+ − 48
public final class Context extends Thread {
+ − 49
/* Used to track threads */
+ − 50
private static long startTime;
+ − 51
private static TurnChecker turn = new TurnChecker(-1);
+ − 52
private static int total_turns_taken;
+ − 53
+ − 54
/* Used for each Context thread */
+ − 55
private final int thread_count;
+ − 56
private final int thread_index;
+ − 57
private final int thread_turns;
+ − 58
+ − 59
/* Main program */
+ − 60
public static void main(String[] argv) throws InterruptedException {
+ − 61
int default_thread_count = 5;
+ − 62
int default_thread_turns = 10;
+ − 63
int default_contention_sleep = 0;
+ − 64
int expected_turns_taken;
+ − 65
long sleepTime = 10L;
+ − 66
+ − 67
/* Override defaults */
+ − 68
if ( argv.length >= 1 ) {
+ − 69
default_thread_count = Integer.parseInt(argv[0]);
+ − 70
}
+ − 71
if ( argv.length >= 2 ) {
+ − 72
expected_turns_taken = Integer.parseInt(argv[1]);
+ − 73
default_thread_turns = expected_turns_taken/default_thread_count;
+ − 74
}
+ − 75
expected_turns_taken = default_thread_count*default_thread_turns;
+ − 76
if ( argv.length >= 3 ) {
+ − 77
default_contention_sleep = Integer.parseInt(argv[2]);
+ − 78
}
+ − 79
+ − 80
System.out.println("Context started with "
+ − 81
+ default_thread_count + " threads and "
+ − 82
+ default_thread_turns + " turns per thread");
+ − 83
+ − 84
/* Get all threads running (they will block until we set turn) */
+ − 85
for (int i = 0; i < default_thread_count; i++) {
+ − 86
new Context(default_thread_count, i, default_thread_turns).start();
+ − 87
}
+ − 88
+ − 89
/* Sleep to make sure thread_index 0 make it to the wait call */
+ − 90
System.out.println("Context sleeping, so threads will start wait");
+ − 91
Thread.yield();
+ − 92
Thread.sleep(sleepTime);
+ − 93
+ − 94
/* Save start time */
+ − 95
startTime = System.currentTimeMillis();
+ − 96
+ − 97
/* This triggers the starting of taking turns */
+ − 98
synchronized (turn) {
+ − 99
turn.thread_index = 0;
+ − 100
turn.notifyAll();
+ − 101
}
+ − 102
System.out.println("Context sleeping, so threads can run");
+ − 103
Thread.yield();
+ − 104
Thread.sleep(sleepTime);
+ − 105
+ − 106
/* Wait for threads to finish (after everyone has had their turns) */
+ − 107
while ( true ) {
+ − 108
boolean done;
+ − 109
done = false;
+ − 110
synchronized (turn) {
+ − 111
if ( total_turns_taken == expected_turns_taken ) {
+ − 112
done = true;
+ − 113
}
+ − 114
/* Create some monitor contention by sleeping with lock */
+ − 115
if ( default_contention_sleep > 0 ) {
+ − 116
System.out.println("Context sleeping, to create contention");
+ − 117
Thread.yield();
+ − 118
Thread.sleep((long)default_contention_sleep);
+ − 119
}
+ − 120
}
+ − 121
if ( done )
+ − 122
break;
+ − 123
System.out.println("Context sleeping, so threads will complete");
+ − 124
Thread.sleep(sleepTime);
+ − 125
}
+ − 126
+ − 127
long endTime = System.currentTimeMillis();
+ − 128
long totalTime = endTime - startTime;
+ − 129
+ − 130
System.out.println("Total time (milliseconds): " + totalTime);
+ − 131
System.out.println("Milliseconds per thread: " +
+ − 132
((double)totalTime / (default_thread_count)));
+ − 133
+ − 134
System.out.println("Context completed");
+ − 135
System.exit(0);
+ − 136
}
+ − 137
+ − 138
/* Thread object to run */
+ − 139
Context(int thread_count, int thread_index, int thread_turns) {
+ − 140
this.thread_count = thread_count;
+ − 141
this.thread_index = thread_index;
+ − 142
this.thread_turns = thread_turns;
+ − 143
}
+ − 144
+ − 145
/* Main for thread */
+ − 146
public void run() {
+ − 147
int next_thread_index = (thread_index + 1) % thread_count;
+ − 148
int turns_taken = 0;
+ − 149
+ − 150
try {
+ − 151
+ − 152
/* Loop until we make sure we get all our turns */
+ − 153
for (int i = 0; i < thread_turns * thread_count; i++) {
+ − 154
synchronized (turn) {
+ − 155
/* Keep waiting for our turn */
+ − 156
while (turn.thread_index != thread_index)
+ − 157
turn.wait();
+ − 158
/* MY TURN! Each thread gets thread_turns */
+ − 159
total_turns_taken++;
+ − 160
turns_taken++;
+ − 161
System.out.println("Turn #" + total_turns_taken
+ − 162
+ " taken by thread " + thread_index
+ − 163
+ ", " + turns_taken
+ − 164
+ " turns taken by this thread");
+ − 165
/* Give next thread a turn */
+ − 166
turn.thread_index = next_thread_index;
+ − 167
turn.notifyAll();
+ − 168
}
+ − 169
/* If we've had all our turns, break out of this loop */
+ − 170
if ( thread_turns == turns_taken ) {
+ − 171
break;
+ − 172
}
+ − 173
}
+ − 174
} catch (InterruptedException intEx) { /* skip */ }
+ − 175
+ − 176
/* Make sure we got all our turns */
+ − 177
if ( thread_turns != turns_taken ) {
+ − 178
System.out.println("ERROR: thread got " + turns_taken
+ − 179
+ " turns, expected " + thread_turns);
+ − 180
System.exit(1);
+ − 181
}
+ − 182
}
+ − 183
}