concurrency chapter progress
This commit is contained in:
parent
afa51c5b7a
commit
6d4d5a1dfc
@ -42,7 +42,6 @@ public class CompletablePizza {
|
||||
}
|
||||
}
|
||||
/* Output:
|
||||
/* Output:
|
||||
56
|
||||
Pizza 0: ROLLED
|
||||
Pizza 1: ROLLED
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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(),
|
||||
|
@ -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
|
||||
*/
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
27
concurrent/StickHolder.java
Normal file
27
concurrent/StickHolder.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user