concurrency chapter progress

This commit is contained in:
Bruce Eckel 2016-12-29 17:05:59 -08:00
parent afa51c5b7a
commit 6d4d5a1dfc
6 changed files with 73 additions and 104 deletions

View File

@ -42,7 +42,6 @@ public class CompletablePizza {
} }
} }
/* Output: /* Output:
/* Output:
56 56
Pizza 0: ROLLED Pizza 0: ROLLED
Pizza 1: ROLLED Pizza 1: ROLLED

View File

@ -2,63 +2,36 @@
// (c)2016 MindView LLC: see Copyright.txt // (c)2016 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose. // We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information. // Visit http://OnJava8.com for more book information.
// Deadlock can be hidden in a program // Hidden deadlock
import java.util.stream.*; import java.util.*;
import java.util.concurrent.*; import java.util.concurrent.*;
import static java.util.concurrent.TimeUnit.*; import static java.util.concurrent.TimeUnit.*;
public class DiningPhilosophers { public class DiningPhilosophers {
static void stopAfter(int secs) { private StickHolder[] sticks;
private Philosopher[] philosophers;
public DiningPhilosophers(int n) {
sticks = new StickHolder[n];
Arrays.setAll(sticks, i -> new StickHolder());
philosophers = new Philosopher[n];
Arrays.setAll(philosophers, i ->
new Philosopher(i,
sticks[i], sticks[(i + 1) % n])); // [1]
// Fix by reversing stick order:
// philosophers[1] = // [2]
// new Philosopher(0, sticks[0], sticks[1]);
Arrays.stream(philosophers)
.forEach(CompletableFuture::runAsync); // [3]
}
public static void main(String[] args) {
// Returns right away:
new DiningPhilosophers(5); // [4]
// Keeps main() from exiting:
ScheduledExecutorService sched = ScheduledExecutorService sched =
Executors.newScheduledThreadPool(1); Executors.newScheduledThreadPool(1);
sched.schedule( () -> { sched.schedule( () -> {
System.out.println("Timeout"); System.out.println("Shutdown");
Philosopher.running.set(false); sched.shutdown();
sched.shutdownNow(); }, 3, SECONDS);
System.exit(0);
}, secs, SECONDS);
}
public static void main(String[] args)
throws Exception {
stopAfter(3);
try {
IntStream.range(0, Philosopher.QUANTITY)
.mapToObj(Philosopher::new)
.map(CompletableFuture::runAsync)
.collect(Collectors.toList())
.forEach(CompletableFuture::join);
} catch(CompletionException ex) {
Philosopher.running.set(false);
System.out.println("Broken out of deadlock");
System.out.println("...");
}
Philosopher.trace.stream()
.skip(Philosopher.trace.size() - 20)
.forEach(System.out::println);
} }
} }
/* Output:
Broken out of deadlock
...
P2 grabbing right
P1 grabbing left
P3 eating
P3 thinking
P3 grabbing right
P4 eating
P2 grabbing left
P4 thinking
P0 eating
P4 grabbing right
P3 grabbing left
P0 thinking
P0 grabbing right
P4 grabbing left
P0 grabbing left
P1 eating
P2 eating
P3 eating
P0 eating
P4 eating
Timeout
*/

View File

@ -3,7 +3,6 @@
// We make no guarantees that this code is fit for any purpose. // We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information. // Visit http://OnJava8.com for more book information.
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.function.*;
import java.util.stream.*; import java.util.stream.*;
import onjava.Nap; import onjava.Nap;
@ -20,6 +19,8 @@ public class FrostedCake {
public FrostedCake(Baked baked, Frosting frosting) { public FrostedCake(Baked baked, Frosting frosting) {
new Nap(100); new Nap(100);
} }
@Override
public String toString() { return "FrostedCake"; }
public static void main(String[] args) { public static void main(String[] args) {
Baked.batch().forEach(baked -> baked Baked.batch().forEach(baked -> baked
.thenCombineAsync(Frosting.make(), .thenCombineAsync(Frosting.make(),

View File

@ -7,7 +7,6 @@ import java.util.stream.*;
import static java.util.stream.LongStream.*; import static java.util.stream.LongStream.*;
import java.io.*; import java.io.*;
import java.nio.file.*; import java.nio.file.*;
import java.nio.charset.*;
import onjava.Timer; import onjava.Timer;
public class ParallelPrime { public class ParallelPrime {
@ -32,6 +31,5 @@ public class ParallelPrime {
} }
} }
/* Output: /* Output:
/* Output:
616 616
*/ */

View File

@ -2,58 +2,29 @@
// (c)2016 MindView LLC: see Copyright.txt // (c)2016 MindView LLC: see Copyright.txt
// We make no guarantees that this code is fit for any purpose. // We make no guarantees that this code is fit for any purpose.
// Visit http://OnJava8.com for more book information. // Visit http://OnJava8.com for more book information.
import java.util.*;
import java.util.stream.*;
import java.util.concurrent.*;
import static java.util.concurrent.TimeUnit.*;
import java.util.concurrent.atomic.*;
class Philosopher implements Runnable { public class Philosopher implements Runnable {
static class Chopstick {} private final int seat;
public static final int QUANTITY = 5; private final StickHolder left, right;
static Queue<String> trace = public Philosopher(int seat,
new ConcurrentLinkedQueue<>(); StickHolder left, StickHolder right) {
static AtomicBoolean running = this.seat = seat;
new AtomicBoolean(true); this.left = left;
public static this.right = right;
List<BlockingQueue<Chopstick>> chopsticks =
IntStream.range(0, Philosopher.QUANTITY)
.mapToObj(i -> {
BlockingQueue<Chopstick> bd =
new ArrayBlockingQueue<>(1);
bd.add(new Chopstick());
return bd;
})
.collect(Collectors.toList());
private final int seatNumber;
private final int left, right;
public Philosopher(int seatNumber) {
this.seatNumber = left = seatNumber;
right = (seatNumber + 1) % QUANTITY;
}
@Override
public void run() {
try {
while(running.get()) {
trace.add(this + " thinking");
// Philosopher becomes hungry
trace.add(this + " grabbing right");
Chopstick rightStick =
chopsticks.get(right).poll(2, SECONDS);
trace.add(this + " grabbing left");
Chopstick leftStick =
chopsticks.get(left).poll(2, SECONDS);
trace.add(this + " eating");
// Finished, return chopsticks to table:
chopsticks.get(right).put(rightStick);
chopsticks.get(left).put(leftStick);
}
} catch(InterruptedException e) {
trace.add("exiting via interrupt");
}
} }
@Override @Override
public String toString() { public String toString() {
return "P" + seatNumber; return "P" + seat;
}
@Override
public void run() {
while(true) {
// System.out.println("Thinking"); // [1]
right.pickUp();
left.pickUp();
System.out.println(this + " eating");
right.putDown();
left.putDown();
}
} }
} }

View File

@ -0,0 +1,27 @@
// concurrent/StickHolder.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 class StickHolder {
private static class Chopstick {}
private Chopstick stick = new Chopstick();
private BlockingQueue<Chopstick> holder =
new ArrayBlockingQueue<>(1);
public StickHolder() { putDown(); }
public void pickUp() {
try {
holder.take(); // Blocks if unavailable
} catch(InterruptedException e) {
throw new RuntimeException(e);
}
}
public void putDown() {
try {
holder.put(stick);
} catch(InterruptedException e) {
throw new RuntimeException(e);
}
}
}