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:
56
Pizza 0: ROLLED
Pizza 1: ROLLED

View File

@ -2,63 +2,36 @@
// (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.
// Deadlock can be hidden in a program
import java.util.stream.*;
// Hidden deadlock
import java.util.*;
import java.util.concurrent.*;
import static java.util.concurrent.TimeUnit.*;
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 =
Executors.newScheduledThreadPool(1);
sched.schedule( () -> {
System.out.println("Timeout");
Philosopher.running.set(false);
sched.shutdownNow();
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);
System.out.println("Shutdown");
sched.shutdown();
}, 3, SECONDS);
}
}
/* 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.
// Visit http://OnJava8.com for more book information.
import java.util.concurrent.*;
import java.util.function.*;
import java.util.stream.*;
import onjava.Nap;
@ -20,6 +19,8 @@ public class FrostedCake {
public FrostedCake(Baked baked, Frosting frosting) {
new Nap(100);
}
@Override
public String toString() { return "FrostedCake"; }
public static void main(String[] args) {
Baked.batch().forEach(baked -> baked
.thenCombineAsync(Frosting.make(),

View File

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

View File

@ -2,58 +2,29 @@
// (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.*;
import static java.util.concurrent.TimeUnit.*;
import java.util.concurrent.atomic.*;
class Philosopher implements Runnable {
static class Chopstick {}
public static final int QUANTITY = 5;
static Queue<String> trace =
new ConcurrentLinkedQueue<>();
static AtomicBoolean running =
new AtomicBoolean(true);
public static
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");
}
public class Philosopher implements Runnable {
private final int seat;
private final StickHolder left, right;
public Philosopher(int seat,
StickHolder left, StickHolder right) {
this.seat = seat;
this.left = left;
this.right = right;
}
@Override
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);
}
}
}