Code from book

Also added some 5-second timeouts in various places to build.xml because
(expected) exceptions were causing ant to hang for a long time, then
inexplicably continue.
This commit is contained in:
Bruce Eckel 2015-04-22 09:30:08 -07:00
parent 40d07cccc4
commit efd9f6d36b
3 changed files with 58 additions and 113 deletions

View File

@ -21,8 +21,7 @@ abstract class Accumulator {
protected String id = "error"; protected String id = "error";
protected final static int SIZE = 100000; protected final static int SIZE = 100000;
protected static int[] preLoaded = new int[SIZE]; protected static int[] preLoaded = new int[SIZE];
static { static { // Load the array of random numbers:
// Load the array of random numbers:
Random rand = new Random(47); Random rand = new Random(47);
for(int i = 0; i < SIZE; i++) for(int i = 0; i < SIZE; i++)
preLoaded[i] = rand.nextInt(); preLoaded[i] = rand.nextInt();
@ -66,24 +65,14 @@ abstract class Accumulator {
duration = System.nanoTime() - start; duration = System.nanoTime() - start;
printf("%-13s: %13d\n", id, duration); printf("%-13s: %13d\n", id, duration);
} }
public static void public void report(Accumulator acc2) {
report(Accumulator acc1, Accumulator acc2) { printf("%-22s: %.2f\n", this.id + "/" + acc2.id,
printf("%-22s: %.2f\n", acc1.id + "/" + acc2.id, (double)this.duration/(double)acc2.duration);
(double)acc1.duration/(double)acc2.duration);
} }
} }
class BaseLine extends Accumulator {
{ id = "BaseLine"; }
public void accumulate() {
value += preLoaded[index++];
if(index >= SIZE) index = 0;
}
public long read() { return value; }
}
class SynchronizedTest extends Accumulator { class SynchronizedTest extends Accumulator {
{ id = "synchronized"; } { id = "synch"; }
public synchronized void accumulate() { public synchronized void accumulate() {
value += preLoaded[index++]; value += preLoaded[index++];
if(index >= SIZE) index = 0; if(index >= SIZE) index = 0;
@ -119,36 +108,36 @@ class AtomicTest extends Accumulator {
{ id = "Atomic"; } { id = "Atomic"; }
private AtomicInteger index = new AtomicInteger(0); private AtomicInteger index = new AtomicInteger(0);
private AtomicLong value = new AtomicLong(0); private AtomicLong value = new AtomicLong(0);
public void accumulate() { // Relying on more than one Atomic at a time doesn't
// Oops! Relying on more than one Atomic at // work, so we still have to synchronize. But it gives
// a time doesn't work. But it still gives us // a performance indicator:
// a performance indicator: public synchronized void accumulate() {
int i = index.getAndIncrement(); int i;
i = index.getAndIncrement();
value.getAndAdd(preLoaded[i]); value.getAndAdd(preLoaded[i]);
if(++i >= SIZE) if(++i >= SIZE)
index.set(0); index.set(0);
} }
public long read() { return value.get(); } public synchronized long read() { return value.get(); }
public void report(Accumulator acc2) {
printf("%-22s: %.2f\n", "synch/(Atomic-synch)",
(double)acc2.duration/
((double)this.duration - (double)acc2.duration));
}
} }
public class SynchronizationComparisons { public class SynchronizationComparisons {
static BaseLine baseLine = new BaseLine();
static SynchronizedTest synch = new SynchronizedTest(); static SynchronizedTest synch = new SynchronizedTest();
static LockTest lock = new LockTest(); static LockTest lock = new LockTest();
static AtomicTest atomic = new AtomicTest(); static AtomicTest atomic = new AtomicTest();
static void test() { static void test() {
print("============================"); print("============================");
printf("%-12s : %13d\n", "Cycles", Accumulator.cycles); printf("%-12s : %13d\n", "Cycles", Accumulator.cycles);
baseLine.timedTest();
synch.timedTest(); synch.timedTest();
lock.timedTest(); lock.timedTest();
atomic.timedTest(); atomic.timedTest();
Accumulator.report(synch, baseLine); synch.report(lock);
Accumulator.report(lock, baseLine); atomic.report(synch);
Accumulator.report(atomic, baseLine);
Accumulator.report(synch, lock);
Accumulator.report(synch, atomic);
Accumulator.report(lock, atomic);
} }
public static void main(String[] args) { public static void main(String[] args) {
int iterations = 5; // Default int iterations = 5; // Default
@ -156,7 +145,7 @@ public class SynchronizationComparisons {
iterations = new Integer(args[0]); iterations = new Integer(args[0]);
// The first time fills the thread pool: // The first time fills the thread pool:
print("Warmup"); print("Warmup");
baseLine.timedTest(); synch.timedTest();
// Now the initial test doesn't include the cost // Now the initial test doesn't include the cost
// of starting the threads for the first time. // of starting the threads for the first time.
// Produce multiple data points: // Produce multiple data points:
@ -166,91 +155,42 @@ public class SynchronizationComparisons {
} }
Accumulator.exec.shutdown(); Accumulator.exec.shutdown();
} }
} /* Output: (Sample) } /* Output: (Sample) using JDK6u10
Warmup Warmup
BaseLine : 34237033 synch : 129868038
============================ ============================
Cycles : 50000 Cycles : 50000
BaseLine : 20966632 synch : 126407922
synchronized : 24326555 Lock : 51207369
Lock : 53669950 Atomic : 141845223
Atomic : 30552487 synch/Lock : 2.47
synchronized/BaseLine : 1.16 synch/(Atomic-synch) : 8.19
Lock/BaseLine : 2.56
Atomic/BaseLine : 1.46
synchronized/Lock : 0.45
synchronized/Atomic : 0.79
Lock/Atomic : 1.76
============================ ============================
Cycles : 100000 Cycles : 100000
BaseLine : 41512818 synch : 251174061
synchronized : 43843003 Lock : 105338114
Lock : 87430386 Atomic : 279503250
Atomic : 51892350 synch/Lock : 2.38
synchronized/BaseLine : 1.06 synch/(Atomic-synch) : 8.87
Lock/BaseLine : 2.11
Atomic/BaseLine : 1.25
synchronized/Lock : 0.50
synchronized/Atomic : 0.84
Lock/Atomic : 1.68
============================ ============================
Cycles : 200000 Cycles : 200000
BaseLine : 80176670 synch : 508778006
synchronized : 5455046661 Lock : 214398402
Lock : 177686829 Atomic : 574464795
Atomic : 101789194 synch/Lock : 2.37
synchronized/BaseLine : 68.04 synch/(Atomic-synch) : 7.75
Lock/BaseLine : 2.22
Atomic/BaseLine : 1.27
synchronized/Lock : 30.70
synchronized/Atomic : 53.59
Lock/Atomic : 1.75
============================ ============================
Cycles : 400000 Cycles : 400000
BaseLine : 160383513 synch : 1027003521
synchronized : 780052493 Lock : 428342577
Lock : 362187652 Atomic : 1115667617
Atomic : 202030984 synch/Lock : 2.40
synchronized/BaseLine : 4.86 synch/(Atomic-synch) : 11.58
Lock/BaseLine : 2.26
Atomic/BaseLine : 1.26
synchronized/Lock : 2.15
synchronized/Atomic : 3.86
Lock/Atomic : 1.79
============================ ============================
Cycles : 800000 Cycles : 800000
BaseLine : 322064955 synch : 2179255097
synchronized : 336155014 Lock : 877216314
Lock : 704615531 Atomic : 2371504710
Atomic : 393231542 synch/Lock : 2.48
synchronized/BaseLine : 1.04 synch/(Atomic-synch) : 11.34
Lock/BaseLine : 2.19
Atomic/BaseLine : 1.22
synchronized/Lock : 0.47
synchronized/Atomic : 0.85
Lock/Atomic : 1.79
============================
Cycles : 1600000
BaseLine : 650004120
synchronized : 52235762925
Lock : 1419602771
Atomic : 796950171
synchronized/BaseLine : 80.36
Lock/BaseLine : 2.18
Atomic/BaseLine : 1.23
synchronized/Lock : 36.80
synchronized/Atomic : 65.54
Lock/Atomic : 1.78
============================
Cycles : 3200000
BaseLine : 1285664519
synchronized : 96336767661
Lock : 2846988654
Atomic : 1590545726
synchronized/BaseLine : 74.93
Lock/BaseLine : 2.21
Atomic/BaseLine : 1.24
synchronized/Lock : 33.84
synchronized/Atomic : 60.57
Lock/Atomic : 1.79
*///:~ *///:~

View File

@ -142,8 +142,10 @@
classname="CaptureUncaughtException" classname="CaptureUncaughtException"
classpath="${java.class.path};${basedir};${basedir}/.." classpath="${java.class.path};${basedir};${basedir}/.."
dir="../concurrency/" dir="../concurrency/"
failonerror="true" failonerror="false"
fork="true"/> fork="true"
timeout="5000"
/>
</target> </target>
<target name="CarBuilder"> <target name="CarBuilder">
@ -244,7 +246,8 @@
classpath="${java.class.path};${basedir};${basedir}/.." classpath="${java.class.path};${basedir};${basedir}/.."
dir="../concurrency/" dir="../concurrency/"
failonerror="false" failonerror="false"
fork="true"/> fork="true"
timeout="5000" />
<echo message="* Exception was expected *"/> <echo message="* Exception was expected *"/>
</target> </target>
@ -417,7 +420,8 @@
classpath="${java.class.path};${basedir};${basedir}/.." classpath="${java.class.path};${basedir};${basedir}/.."
dir="../concurrency/" dir="../concurrency/"
failonerror="false" failonerror="false"
fork="true"/> fork="true"
timeout="5000"/>
<echo message="* Exception was expected *"/> <echo message="* Exception was expected *"/>
</target> </target>
@ -527,8 +531,9 @@
classname="SettingDefaultHandler" classname="SettingDefaultHandler"
classpath="${java.class.path};${basedir};${basedir}/.." classpath="${java.class.path};${basedir};${basedir}/.."
dir="../concurrency/" dir="../concurrency/"
failonerror="true" failonerror="false"
fork="true"/> fork="true"
timeout="5000"/>
</target> </target>
<target name="SimpleDaemons"> <target name="SimpleDaemons">