diff --git a/concurrent/CachedThreadPool.java b/concurrent/CachedThreadPool.java index 1cd48564..1c35c184 100644 --- a/concurrent/CachedThreadPool.java +++ b/concurrent/CachedThreadPool.java @@ -12,7 +12,6 @@ public class CachedThreadPool { for(int id = 0; id < 10; id++) exec.execute(new SleepAndPrintTask(id)); exec.shutdown(); - exec.awaitTermination(5, TimeUnit.SECONDS); } } /* Output: diff --git a/concurrent/CachedThreadPool2.java b/concurrent/CachedThreadPool2.java index 3c66da6d..55119ce9 100644 --- a/concurrent/CachedThreadPool2.java +++ b/concurrent/CachedThreadPool2.java @@ -12,7 +12,6 @@ public class CachedThreadPool2 { for(int id = 0; id < 10; id++) exec.execute(new InterferingTask(id)); exec.shutdown(); - exec.awaitTermination(5, TimeUnit.SECONDS); } } /* Output: diff --git a/concurrent/LambdasAndMethodReferences.java b/concurrent/LambdasAndMethodReferences.java index 2e713d46..9b7813aa 100644 --- a/concurrent/LambdasAndMethodReferences.java +++ b/concurrent/LambdasAndMethodReferences.java @@ -30,7 +30,6 @@ public class LambdasAndMethodReferences { }); exec.submit(new NotCallable()::get); exec.shutdown(); - exec.awaitTermination(1, TimeUnit.SECONDS); } } /* Output: diff --git a/concurrent/MoreTasksAfterShutdown.java b/concurrent/MoreTasksAfterShutdown.java index a940bd67..15ca9a6d 100644 --- a/concurrent/MoreTasksAfterShutdown.java +++ b/concurrent/MoreTasksAfterShutdown.java @@ -16,7 +16,6 @@ public class MoreTasksAfterShutdown { } catch(RejectedExecutionException e) { System.out.println(e); } - exec.awaitTermination(5, TimeUnit.SECONDS); } } /* Output: diff --git a/concurrent/OnePizza.java b/concurrent/OnePizza.java new file mode 100644 index 00000000..608821c7 --- /dev/null +++ b/concurrent/OnePizza.java @@ -0,0 +1,26 @@ +// concurrent/OnePizza.java +// (c)2016 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import onjava.Timer; + +public class OnePizza { + public static void main(String[] args) { + Pizza za = new Pizza(0); + System.out.println( + Timer.duration(() -> { + while(!za.complete()) + za.next(); + })); + } +} +/* Output: +Pizza 0: ROLLED +Pizza 0: SAUCED +Pizza 0: CHEESED +Pizza 0: TOPPED +Pizza 0: BAKED +Pizza 0: SLICED +Pizza 0: BOXED +1612 +*/ diff --git a/concurrent/ParallelPrime.java b/concurrent/ParallelPrime.java index 14c6a184..597f645e 100644 --- a/concurrent/ParallelPrime.java +++ b/concurrent/ParallelPrime.java @@ -8,6 +8,7 @@ import static java.util.stream.LongStream.*; import java.io.*; import java.nio.file.*; import java.nio.charset.*; +import onjava.Timer; public class ParallelPrime { static final int COUNT = 100_000; @@ -17,7 +18,7 @@ public class ParallelPrime { } public static void main(String[] args) throws IOException { - long start = System.currentTimeMillis(); + Timer timer = new Timer(); List primes = iterate(2, i -> i + 1) .parallel() // [1] @@ -25,8 +26,7 @@ public class ParallelPrime { .limit(COUNT) .mapToObj(Long::toString) .collect(Collectors.toList()); - System.out.println( - System.currentTimeMillis() - start); + System.out.println(timer.duration()); Files.write(Paths.get("primes.txt"), primes, StandardOpenOption.CREATE); } diff --git a/concurrent/Pizza.java b/concurrent/Pizza.java new file mode 100644 index 00000000..0eeb2156 --- /dev/null +++ b/concurrent/Pizza.java @@ -0,0 +1,46 @@ +// concurrent/Pizza.java +// (c)2016 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import static java.util.concurrent.TimeUnit.*; + +public class Pizza { + public enum Step { + DOUGH(4), ROLLED(1), SAUCED(1), CHEESED(2), + TOPPED(5), BAKED(2), SLICED(1), BOXED(0); + int effort; // Needed to get to the next step + Step(int effort) { this.effort = effort; } + Step forward() { + if(equals(BOXED)) return BOXED; + try { + MILLISECONDS.sleep(effort * 100); + } catch(InterruptedException e) { + throw new RuntimeException(e); + } + return values()[ordinal() + 1]; + } + } + private Step step = Step.DOUGH; + private final int id; + public Pizza(int id) { this.id = id; } + public void next() { + step = step.forward(); + System.out.println("Pizza " + id + ": " + step); + } + public void next(Step previousStep) { + if(!step.equals(previousStep)) + throw new IllegalStateException("Expected " + + previousStep + " but found " + step); + next(); + } + public void roll() { next(Step.DOUGH); } + public void sauce() { next(Step.ROLLED); } + public void cheese() { next(Step.SAUCED); } + public void toppings() { next(Step.CHEESED); } + public void bake() { next(Step.TOPPED); } + public void slice() { next(Step.BAKED); } + public void box() { next(Step.SLICED); } + public boolean complete() { + return step.equals(Step.BOXED); + } +} diff --git a/concurrent/PizzaStreams.java b/concurrent/PizzaStreams.java new file mode 100644 index 00000000..d29f7557 --- /dev/null +++ b/concurrent/PizzaStreams.java @@ -0,0 +1,60 @@ +// concurrent/PizzaStreams.java +// (c)2016 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import onjava.Timer; + +public class PizzaStreams { + static int QUANTITY = 5; + public static void main(String[] args) { + Timer timer = new Timer(); + IntStream.range(0, QUANTITY) + .mapToObj(Pizza::new) + .parallel() // [1] + .forEach(za -> { + while(!za.complete()) + za.next(); + }); + System.out.println(timer.duration()); + } +} +/* Output: +Pizza 4: ROLLED +Pizza 2: ROLLED +Pizza 0: ROLLED +Pizza 3: ROLLED +Pizza 1: ROLLED +Pizza 0: SAUCED +Pizza 3: SAUCED +Pizza 4: SAUCED +Pizza 1: SAUCED +Pizza 2: SAUCED +Pizza 0: CHEESED +Pizza 4: CHEESED +Pizza 3: CHEESED +Pizza 2: CHEESED +Pizza 1: CHEESED +Pizza 3: TOPPED +Pizza 4: TOPPED +Pizza 0: TOPPED +Pizza 2: TOPPED +Pizza 1: TOPPED +Pizza 0: BAKED +Pizza 3: BAKED +Pizza 4: BAKED +Pizza 1: BAKED +Pizza 2: BAKED +Pizza 4: SLICED +Pizza 3: SLICED +Pizza 0: SLICED +Pizza 2: SLICED +Pizza 1: SLICED +Pizza 3: BOXED +Pizza 4: BOXED +Pizza 0: BOXED +Pizza 1: BOXED +Pizza 2: BOXED +1667 +*/ diff --git a/concurrent/QuittableTask.java b/concurrent/QuittableTask.java new file mode 100644 index 00000000..6d8a535e --- /dev/null +++ b/concurrent/QuittableTask.java @@ -0,0 +1,24 @@ +// concurrent/QuittableTask.java +// (c)2016 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.concurrent.*; +import java.util.concurrent.atomic.AtomicBoolean; + +public class QuittableTask implements Runnable { + final int id; + public QuittableTask(int id) { this.id = id; } + private AtomicBoolean running = + new AtomicBoolean(true); + public void quit() { running.set(false); } + @Override + public void run() { + while(running.get()) // [1] + try { + TimeUnit.MILLISECONDS.sleep(100); + } catch(InterruptedException e) { + throw new RuntimeException(e); + } + System.out.print(id + " "); // [2] + } +} diff --git a/concurrent/QuittingTasks.java b/concurrent/QuittingTasks.java new file mode 100644 index 00000000..fb15aa57 --- /dev/null +++ b/concurrent/QuittingTasks.java @@ -0,0 +1,24 @@ +// concurrent/QuittingTasks.java +// (c)2016 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +import java.util.*; +import java.util.stream.*; +import java.util.concurrent.*; + +public class QuittingTasks { + public static final int COUNT = 150; + public static void main(String[] args) + throws InterruptedException { + ExecutorService es = + Executors.newCachedThreadPool(); + List tasks = + IntStream.range(1, COUNT) + .mapToObj(QuittableTask::new) + .peek(qt -> es.execute(qt)) + .collect(Collectors.toList()); + TimeUnit.SECONDS.sleep(1); + tasks.forEach(QuittableTask::quit); + es.shutdown(); + } +} diff --git a/concurrent/SingleThreadExecutor2.java b/concurrent/SingleThreadExecutor2.java index 2166b9b6..7c3066b5 100644 --- a/concurrent/SingleThreadExecutor2.java +++ b/concurrent/SingleThreadExecutor2.java @@ -12,7 +12,6 @@ public class SingleThreadExecutor2 { for(int id = 0; id < 10; id++) exec.execute(new SleepAndPrintTask(id)); exec.shutdown(); - exec.awaitTermination(5, TimeUnit.SECONDS); } } /* Output: diff --git a/concurrent/SingleThreadExecutor3.java b/concurrent/SingleThreadExecutor3.java index c90b9505..35f373fd 100644 --- a/concurrent/SingleThreadExecutor3.java +++ b/concurrent/SingleThreadExecutor3.java @@ -12,7 +12,6 @@ public class SingleThreadExecutor3 { for(int id = 0; id < 10; id++) exec.execute(new InterferingTask(id)); exec.shutdown(); - exec.awaitTermination(5, TimeUnit.SECONDS); } } /* Output: diff --git a/concurrent/Summing.java b/concurrent/Summing.java index 99fc4eb3..be59c85c 100644 --- a/concurrent/Summing.java +++ b/concurrent/Summing.java @@ -4,17 +4,17 @@ // Visit http://OnJava8.com for more book information. import java.util.stream.*; import java.util.function.*; +import onjava.Timer; public class Summing { static volatile long x; static void timeTest(String id, long checkValue, LongSupplier operation) { System.out.print(id + ": "); - long t = System.currentTimeMillis(); + Timer timer = new Timer(); long result = operation.getAsLong(); - long duration = System.currentTimeMillis() - t; if(result == checkValue) - System.out.println(duration + "ms"); + System.out.println(timer.duration() + "ms"); else System.out.format("result: %d%ncheckValue: %d%n", result, checkValue); diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 94051b31..ab0ff321 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -2,4 +2,4 @@ distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-3.2-bin.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.2.1-bin.zip diff --git a/onjava/TimedAbort.java b/onjava/TimedAbort.java index b4be68c1..989515ea 100644 --- a/onjava/TimedAbort.java +++ b/onjava/TimedAbort.java @@ -8,7 +8,7 @@ import java.util.*; public class TimedAbort { public TimedAbort(int n) { - new Timer().schedule(new TimerTask() { + new java.util.Timer().schedule(new TimerTask() { @Override public void run() { System.out.println("TimedAbort " + n); diff --git a/onjava/Timer.java b/onjava/Timer.java new file mode 100644 index 00000000..722f777f --- /dev/null +++ b/onjava/Timer.java @@ -0,0 +1,19 @@ +// onjava/Timer.java +// (c)2016 MindView LLC: see Copyright.txt +// We make no guarantees that this code is fit for any purpose. +// Visit http://OnJava8.com for more book information. +package onjava; +import static java.util.concurrent.TimeUnit.*; + +public class Timer { + private long start = System.nanoTime(); + public long duration() { + return NANOSECONDS.toMillis( + System.nanoTime() - start); + } + public static long duration(Runnable test) { + Timer timer = new Timer(); + test.run(); + return timer.duration(); + } +} diff --git a/references/Compete.java b/references/Compete.java index 0d3d96f1..5ec06bcd 100644 --- a/references/Compete.java +++ b/references/Compete.java @@ -3,6 +3,7 @@ // We make no guarantees that this code is fit for any purpose. // Visit http://OnJava8.com for more book information. import java.io.*; +import onjava.Timer; class Thing1 implements Serializable {} class Thing2 implements Serializable { @@ -46,7 +47,7 @@ public class Compete { Thing4[] b = new Thing4[SIZE]; for(int i = 0; i < SIZE; i++) b[i] = new Thing4(); - long t1 = System.currentTimeMillis(); + Timer timer = new Timer(); try( ByteArrayOutputStream buf = new ByteArrayOutputStream(); @@ -68,20 +69,18 @@ public class Compete { c[i] = (Thing2)in.readObject(); } } - long t2 = System.currentTimeMillis(); System.out.println( "Duplication via serialization: " + - (t2 - t1) + " Milliseconds"); + timer.duration() + " Milliseconds"); // Now try cloning: - t1 = System.currentTimeMillis(); + timer = new Timer(); Thing4[] d = new Thing4[SIZE]; for(int i = 0; i < SIZE; i++) d[i] = b[i].clone(); - t2 = System.currentTimeMillis(); System.out.println( "Duplication via cloning: " + - (t2 - t1) + " Milliseconds"); + timer.duration() + " Milliseconds"); } } /* Output: diff --git a/validating/BadMicroBenchmark.java b/validating/BadMicroBenchmark.java index 8e67e947..ba7beb5e 100644 --- a/validating/BadMicroBenchmark.java +++ b/validating/BadMicroBenchmark.java @@ -3,16 +3,19 @@ // We make no guarantees that this code is fit for any purpose. // Visit http://OnJava8.com for more book information. import java.util.*; +import onjava.Timer; public class BadMicroBenchmark { static final int SIZE = 250_000_000; public static void main(String[] args) { try { // For machines with insufficient memory long[] la = new long[SIZE]; - System.out.print("setAll: "); - Time.it(() -> Arrays.setAll(la, n -> n)); - System.out.print("parallelSetAll: "); - Time.it(() -> Arrays.parallelSetAll(la, n -> n)); + System.out.println("setAll: " + + Timer.duration(() -> + Arrays.setAll(la, n -> n))); + System.out.println("parallelSetAll: " + + Timer.duration(() -> + Arrays.parallelSetAll(la, n -> n))); } catch(OutOfMemoryError e) { System.out.println("Insufficient memory"); System.exit(0); diff --git a/validating/BadMicroBenchmark2.java b/validating/BadMicroBenchmark2.java index 3372b338..b1a53597 100644 --- a/validating/BadMicroBenchmark2.java +++ b/validating/BadMicroBenchmark2.java @@ -4,6 +4,7 @@ // Visit http://OnJava8.com for more book information. // Relying on a common resource import java.util.*; +import onjava.Timer; public class BadMicroBenchmark2 { // SIZE reduced to make it run faster: @@ -11,19 +12,19 @@ public class BadMicroBenchmark2 { public static void main(String[] args) { long[] la = new long[SIZE]; Random r = new Random(); - System.out.print("parallelSetAll: "); - Time.it(() -> - Arrays.parallelSetAll(la, n -> r.nextLong())); - System.out.print("setAll: "); - Time.it(() -> - Arrays.setAll(la, n -> r.nextLong())); + System.out.println("parallelSetAll: " + + Timer.duration(() -> + Arrays.parallelSetAll(la, n -> r.nextLong()))); + System.out.println("setAll: " + + Timer.duration(() -> + Arrays.setAll(la, n -> r.nextLong()))); SplittableRandom sr = new SplittableRandom(); - System.out.print("parallelSetAll: "); - Time.it(() -> - Arrays.parallelSetAll(la, n -> sr.nextLong())); - System.out.print("setAll: "); - Time.it(() -> - Arrays.setAll(la, n -> sr.nextLong())); + System.out.println("parallelSetAll: " + + Timer.duration(() -> + Arrays.parallelSetAll(la, n -> sr.nextLong()))); + System.out.println("setAll: " + + Timer.duration(() -> + Arrays.setAll(la, n -> sr.nextLong()))); } } /* Output: diff --git a/validating/Time.java b/validating/Time.java deleted file mode 100644 index 253bdea8..00000000 --- a/validating/Time.java +++ /dev/null @@ -1,16 +0,0 @@ -// validating/Time.java -// (c)2016 MindView LLC: see Copyright.txt -// We make no guarantees that this code is fit for any purpose. -// Visit http://OnJava8.com for more book information. -import java.util.concurrent.*; - -public interface Time { - static long it(Runnable test) { - long start = System.nanoTime(); - test.run(); - long delta = System.nanoTime() - start; - long millis = TimeUnit.NANOSECONDS.toMillis(delta); - System.out.println(millis); - return millis; - } -}