Skip to content

Commit 6d4d5a1

Browse files
author
Bruce Eckel
committed
concurrency chapter progress
1 parent afa51c5 commit 6d4d5a1

6 files changed

Lines changed: 72 additions & 103 deletions

File tree

concurrent/CompletablePizza.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@ public static void main(String[] args) {
4242
}
4343
}
4444
/* Output:
45-
/* Output:
4645
56
4746
Pizza 0: ROLLED
4847
Pizza 1: ROLLED

concurrent/DiningPhilosophers.java

Lines changed: 24 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -2,63 +2,36 @@
22
// (c)2016 MindView LLC: see Copyright.txt
33
// We make no guarantees that this code is fit for any purpose.
44
// Visit http://OnJava8.com for more book information.
5-
// Deadlock can be hidden in a program
6-
import java.util.stream.*;
5+
// Hidden deadlock
6+
import java.util.*;
77
import java.util.concurrent.*;
88
import static java.util.concurrent.TimeUnit.*;
99

1010
public class DiningPhilosophers {
11-
static void stopAfter(int secs) {
11+
private StickHolder[] sticks;
12+
private Philosopher[] philosophers;
13+
public DiningPhilosophers(int n) {
14+
sticks = new StickHolder[n];
15+
Arrays.setAll(sticks, i -> new StickHolder());
16+
philosophers = new Philosopher[n];
17+
Arrays.setAll(philosophers, i ->
18+
new Philosopher(i,
19+
sticks[i], sticks[(i + 1) % n])); // [1]
20+
// Fix by reversing stick order:
21+
// philosophers[1] = // [2]
22+
// new Philosopher(0, sticks[0], sticks[1]);
23+
Arrays.stream(philosophers)
24+
.forEach(CompletableFuture::runAsync); // [3]
25+
}
26+
public static void main(String[] args) {
27+
// Returns right away:
28+
new DiningPhilosophers(5); // [4]
29+
// Keeps main() from exiting:
1230
ScheduledExecutorService sched =
1331
Executors.newScheduledThreadPool(1);
1432
sched.schedule( () -> {
15-
System.out.println("Timeout");
16-
Philosopher.running.set(false);
17-
sched.shutdownNow();
18-
System.exit(0);
19-
}, secs, SECONDS);
20-
}
21-
public static void main(String[] args)
22-
throws Exception {
23-
stopAfter(3);
24-
try {
25-
IntStream.range(0, Philosopher.QUANTITY)
26-
.mapToObj(Philosopher::new)
27-
.map(CompletableFuture::runAsync)
28-
.collect(Collectors.toList())
29-
.forEach(CompletableFuture::join);
30-
} catch(CompletionException ex) {
31-
Philosopher.running.set(false);
32-
System.out.println("Broken out of deadlock");
33-
System.out.println("...");
34-
}
35-
Philosopher.trace.stream()
36-
.skip(Philosopher.trace.size() - 20)
37-
.forEach(System.out::println);
33+
System.out.println("Shutdown");
34+
sched.shutdown();
35+
}, 3, SECONDS);
3836
}
3937
}
40-
/* Output:
41-
Broken out of deadlock
42-
...
43-
P2 grabbing right
44-
P1 grabbing left
45-
P3 eating
46-
P3 thinking
47-
P3 grabbing right
48-
P4 eating
49-
P2 grabbing left
50-
P4 thinking
51-
P0 eating
52-
P4 grabbing right
53-
P3 grabbing left
54-
P0 thinking
55-
P0 grabbing right
56-
P4 grabbing left
57-
P0 grabbing left
58-
P1 eating
59-
P2 eating
60-
P3 eating
61-
P0 eating
62-
P4 eating
63-
Timeout
64-
*/

concurrent/FrostedCake.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
// We make no guarantees that this code is fit for any purpose.
44
// Visit http://OnJava8.com for more book information.
55
import java.util.concurrent.*;
6-
import java.util.function.*;
76
import java.util.stream.*;
87
import onjava.Nap;
98

@@ -20,6 +19,8 @@ public class FrostedCake {
2019
public FrostedCake(Baked baked, Frosting frosting) {
2120
new Nap(100);
2221
}
22+
@Override
23+
public String toString() { return "FrostedCake"; }
2324
public static void main(String[] args) {
2425
Baked.batch().forEach(baked -> baked
2526
.thenCombineAsync(Frosting.make(),

concurrent/ParallelPrime.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,6 @@
77
import static java.util.stream.LongStream.*;
88
import java.io.*;
99
import java.nio.file.*;
10-
import java.nio.charset.*;
1110
import onjava.Timer;
1211

1312
public class ParallelPrime {
@@ -32,6 +31,5 @@ public static void main(String[] args)
3231
}
3332
}
3433
/* Output:
35-
/* Output:
3634
616
3735
*/

concurrent/Philosopher.java

Lines changed: 19 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -2,58 +2,29 @@
22
// (c)2016 MindView LLC: see Copyright.txt
33
// We make no guarantees that this code is fit for any purpose.
44
// Visit http://OnJava8.com for more book information.
5-
import java.util.*;
6-
import java.util.stream.*;
7-
import java.util.concurrent.*;
8-
import static java.util.concurrent.TimeUnit.*;
9-
import java.util.concurrent.atomic.*;
105

11-
class Philosopher implements Runnable {
12-
static class Chopstick {}
13-
public static final int QUANTITY = 5;
14-
static Queue<String> trace =
15-
new ConcurrentLinkedQueue<>();
16-
static AtomicBoolean running =
17-
new AtomicBoolean(true);
18-
public static
19-
List<BlockingQueue<Chopstick>> chopsticks =
20-
IntStream.range(0, Philosopher.QUANTITY)
21-
.mapToObj(i -> {
22-
BlockingQueue<Chopstick> bd =
23-
new ArrayBlockingQueue<>(1);
24-
bd.add(new Chopstick());
25-
return bd;
26-
})
27-
.collect(Collectors.toList());
28-
private final int seatNumber;
29-
private final int left, right;
30-
public Philosopher(int seatNumber) {
31-
this.seatNumber = left = seatNumber;
32-
right = (seatNumber + 1) % QUANTITY;
6+
public class Philosopher implements Runnable {
7+
private final int seat;
8+
private final StickHolder left, right;
9+
public Philosopher(int seat,
10+
StickHolder left, StickHolder right) {
11+
this.seat = seat;
12+
this.left = left;
13+
this.right = right;
3314
}
3415
@Override
35-
public void run() {
36-
try {
37-
while(running.get()) {
38-
trace.add(this + " thinking");
39-
// Philosopher becomes hungry
40-
trace.add(this + " grabbing right");
41-
Chopstick rightStick =
42-
chopsticks.get(right).poll(2, SECONDS);
43-
trace.add(this + " grabbing left");
44-
Chopstick leftStick =
45-
chopsticks.get(left).poll(2, SECONDS);
46-
trace.add(this + " eating");
47-
// Finished, return chopsticks to table:
48-
chopsticks.get(right).put(rightStick);
49-
chopsticks.get(left).put(leftStick);
50-
}
51-
} catch(InterruptedException e) {
52-
trace.add("exiting via interrupt");
53-
}
16+
public String toString() {
17+
return "P" + seat;
5418
}
5519
@Override
56-
public String toString() {
57-
return "P" + seatNumber;
20+
public void run() {
21+
while(true) {
22+
// System.out.println("Thinking"); // [1]
23+
right.pickUp();
24+
left.pickUp();
25+
System.out.println(this + " eating");
26+
right.putDown();
27+
left.putDown();
28+
}
5829
}
5930
}

concurrent/StickHolder.java

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
// concurrent/StickHolder.java
2+
// (c)2016 MindView LLC: see Copyright.txt
3+
// We make no guarantees that this code is fit for any purpose.
4+
// Visit http://OnJava8.com for more book information.
5+
import java.util.concurrent.*;
6+
7+
public class StickHolder {
8+
private static class Chopstick {}
9+
private Chopstick stick = new Chopstick();
10+
private BlockingQueue<Chopstick> holder =
11+
new ArrayBlockingQueue<>(1);
12+
public StickHolder() { putDown(); }
13+
public void pickUp() {
14+
try {
15+
holder.take(); // Blocks if unavailable
16+
} catch(InterruptedException e) {
17+
throw new RuntimeException(e);
18+
}
19+
}
20+
public void putDown() {
21+
try {
22+
holder.put(stick);
23+
} catch(InterruptedException e) {
24+
throw new RuntimeException(e);
25+
}
26+
}
27+
}

0 commit comments

Comments
 (0)