I had to admit that I fired off my earlier e-mail with potentially dated
information (its been a couple of years since I last tested thread
behavior).
So I decided to run a small experiment. I created a simple test class
called ThreadTest: two threads racing each other in a counting loop.
The first one to finish prints out the progress of the other.
I then performed the following runs (not really experiments since I
did not measure deviation):
SAME: Both threads running on the same priority
THREAD1: Thread1 has higher priority (thread2 set to MIN_PRIORITY)
THREAD2: Thread2 has higher priority (thread1 set to MIN_PRIORITY)
YIELD: As in experiment THREAD1, thread1 executing with higher priority,
but yielding every 1000 counts
NOOP: As in experiment THREAD1, thread1 executing with higher priority,
but invoking a noop() method every 1000 counts
I'm attaching the ThreadTest source code.
NOTE: The benchmark was executed once only so the results do not include
standard deviation measurements (see end of note for the raw output).
The JVMs were invoked with no flags except the -classpath flag, hence
were running in client HotSpot mode (see raw output).
PlatformJDK/JVM SAME THREAD1 THREAD2 YIELD NOOP
---s--
Windows XP/i686 Sun 1.4.1_01 99% 1[1%]1[1%]1[6%] 1[6%]
Linux 2.4.18/i686 Sun 1.4.0_02 99% 99% 99% 2[13%] 2[14%]
Linux 2.4.18/i686 Bdwn 1.4.1-beta 99% 99% 99% 2[14%] 2[14%]
Solaris 5.8/sun4u Sun 1.4.1_01-b01 99% 99%
Notes:
x[p%] = thread x finished first with thread !x having completed p%
Seems like there are significant differences between platforms.
A. Windows actually enforces priorities, effectively starving
the lower priority process.
B. Windows yield() has slows down the high priority process, giving the
lower priority process chance to complete additional 5% work.
However, invoking an empty noop() method has the same effect,
so yield() appears to be a no-OP.
C. Linux does not appear to respect priorities. No discernible difference
between Blackdown and Sun's JVMs.
D. Linux yield() again has the same effect as a no-op, but the
results are radically different. The order in which the threads
terminate is switched, that is, the lower priority thread terminates
first, before the highest priority thread even gets a chance to
complete its work! I don't have any off-hand explanation for this.
E. Solaris also does not enforce priorities
RAW OUTPUT:
*** Windows XP/i686 + Sun JDK1.4.1_01
$ uname -a
CYGWIN_NT-5.1 manticore 1.3.19(0.71/3/2) 2003-01-23 21:31 i686 unknown unknown C
ygwin
$ java -version
java version "1.4.1_01"
Java(TM) 2 Runtime Environment, Standard Edition (build 1.4.1_01-b01)
Java HotSpot(TM) Client VM (build 1.4.1_01-b01, mixed mode)
$ java -classpath . ThreadTest
Thread1 30534 ms [peer counter=987704688 (98%) ] isYield=false isNoop=false
Thread2 30724 ms [peer counter=10 (100%) ] isYield=false isNoop=false
$ java -classpath . ThreadTest thread1
Thread1 13149 ms [peer counter=30475575 (3%) ] isYield=false isNoop=false
Thread2 21490 ms [peer counter=10 (100%) ] isYield=false isNoop=false
$ java -classpath . ThreadTest thread2
Thread2 15131 ms [peer counter=12481585 (1%) ] isYield=false isNoop=false
Thread1 26037 ms [peer counter=10 (100%) ] isYield=false isNoop=false
$ java -classpath . ThreadTest thread1 yield
Thread1 100185 ms [peer counter=67353348 (6%) ] isYield=true isNoop=false
Thread2 111200 ms [peer counter=10 (100%) ] isYield=false isNoop=false
$ java -classpath . ThreadTest thread1 noop
Thread1 97070 ms [peer counter=60277822 (6%) ] isYield=false isNoop=true
Thread2 107434 ms [peer counter=10 (100%) ] isYield=false isNoop=false
*** RedHat 7.3 Linux 2.4.18-19.7.x (BLACKDOWN)
$ uname -a
Linux vader.cs.columbia.edu 2.4.18-19.7.x #1 Thu Dec 12 09:00:42 EST 2002 i686
unknown
$ java -version
java version "1.4.1"
Java(TM) 2 Runtime Environment, Standard Edition (build Blackdown-1.4.1-beta)
Java HotSpot(TM) Client VM (build Blackdown-1.4.1-beta, mixed mode)
$ java -classpath . ThreadTest
Thread1 23006 ms [peer counter=992141964 (99%) ] isYield=false isNoop=false
Thread2 22621 ms [peer counter=10 (100%) ] isYield=false isNoop=false
$ java -classpath . ThreadTest thread1
Thread1 23243 ms [peer counter=993677801 (99%) ] isYield=false isNoop=false
Thread2 22851 ms [peer counter=10 (100%) ] isYield=false isNoop=false
$ java -classpath . ThreadTest thread2
Thread1 23029 ms [peer counter=993031008 (99%) ] isYield=false isNoop=false
Thread2 22648 ms [peer counter=10 (100%) ] isYield=false isNoop=false
$ java -classpath . ThreadTest thread1 yield
Thread2 23136 ms [peer counter=142112359 (14%) ] isYield=false isNoop=false
Thread1 93062 ms [peer counter=10 (100%) ] isYield=true isNoop=false
$ java -classpath . ThreadTest thread1 no