Moved examples from "Concurrent" to "lowlevel"
This commit is contained in:
parent
c590aeb851
commit
afa51c5b7a
31
concurrent/Baked.java
Normal file
31
concurrent/Baked.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// concurrent/Baked.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.stream.*;
|
||||||
|
import onjava.Nap;
|
||||||
|
|
||||||
|
public class Baked {
|
||||||
|
static class Pan {}
|
||||||
|
static Pan pan(Batter b) {
|
||||||
|
new Nap(100);
|
||||||
|
return new Pan();
|
||||||
|
}
|
||||||
|
static Baked heat(Pan p) {
|
||||||
|
new Nap(100);
|
||||||
|
return new Baked();
|
||||||
|
}
|
||||||
|
static CompletableFuture<Baked>
|
||||||
|
bake(CompletableFuture<Batter> cfb) {
|
||||||
|
return cfb
|
||||||
|
.thenApplyAsync(Baked::pan)
|
||||||
|
.thenApplyAsync(Baked::heat);
|
||||||
|
}
|
||||||
|
public static
|
||||||
|
Stream<CompletableFuture<Baked>> batch() {
|
||||||
|
CompletableFuture<Batter> batter = Batter.mix();
|
||||||
|
return Stream.of(bake(batter), bake(batter),
|
||||||
|
bake(batter), bake(batter));
|
||||||
|
}
|
||||||
|
}
|
34
concurrent/Batter.java
Normal file
34
concurrent/Batter.java
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// concurrent/Batter.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 onjava.Nap;
|
||||||
|
|
||||||
|
public class Batter {
|
||||||
|
static class Eggs {}
|
||||||
|
static class Milk {}
|
||||||
|
static class Sugar {}
|
||||||
|
static class Flour {}
|
||||||
|
static <T> T prepare(T ingredient) {
|
||||||
|
new Nap(100);
|
||||||
|
return ingredient;
|
||||||
|
}
|
||||||
|
static <T> CompletableFuture<T> cf(T ingredient) {
|
||||||
|
return CompletableFuture
|
||||||
|
.completedFuture(ingredient)
|
||||||
|
.thenApply(Batter::prepare);
|
||||||
|
}
|
||||||
|
public static CompletableFuture<Batter> mix() {
|
||||||
|
CompletableFuture<Eggs> eggs = cf(new Eggs());
|
||||||
|
CompletableFuture<Milk> milk = cf(new Milk());
|
||||||
|
CompletableFuture<Sugar> sugar = cf(new Sugar());
|
||||||
|
CompletableFuture<Flour> flour = cf(new Flour());
|
||||||
|
CompletableFuture
|
||||||
|
.allOf(eggs, milk, sugar, flour)
|
||||||
|
.join();
|
||||||
|
new Nap(100); // Mixing time
|
||||||
|
return
|
||||||
|
CompletableFuture.completedFuture(new Batter());
|
||||||
|
}
|
||||||
|
}
|
26
concurrent/Breakable.java
Normal file
26
concurrent/Breakable.java
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// concurrent/Breakable.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 Breakable {
|
||||||
|
String id;
|
||||||
|
private int failcount;
|
||||||
|
public Breakable(String id, int failcount) {
|
||||||
|
this.id = id;
|
||||||
|
this.failcount = failcount;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Breakable_" + id +
|
||||||
|
" [" + failcount + "]";
|
||||||
|
}
|
||||||
|
public static Breakable work(Breakable b) {
|
||||||
|
if(--b.failcount == 0)
|
||||||
|
throw new RuntimeException(
|
||||||
|
"Breakable_" + b.id + " failed");
|
||||||
|
System.out.println(b);
|
||||||
|
return b;
|
||||||
|
}
|
||||||
|
}
|
79
concurrent/CatchCompletableExceptions.java
Normal file
79
concurrent/CatchCompletableExceptions.java
Normal file
@ -0,0 +1,79 @@
|
|||||||
|
// concurrent/CatchCompletableExceptions.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 onjava.Nap;
|
||||||
|
|
||||||
|
public class CatchCompletableExceptions {
|
||||||
|
static void handleException(int failcount) {
|
||||||
|
// Call Function only if there's an exception,
|
||||||
|
// Must produce same type as came in:
|
||||||
|
CompletableExceptions
|
||||||
|
.test("exceptionally", failcount)
|
||||||
|
.exceptionally((ex) -> { // Function
|
||||||
|
if(ex == null)
|
||||||
|
System.out.println("I don't get it yet");
|
||||||
|
return new Breakable(ex.getMessage(), 0);
|
||||||
|
})
|
||||||
|
.thenAccept(str ->
|
||||||
|
System.out.println("result: " + str));
|
||||||
|
|
||||||
|
// Create a new result (recover):
|
||||||
|
CompletableExceptions
|
||||||
|
.test("handle", failcount)
|
||||||
|
.handle((result, fail) -> { // BiFunction
|
||||||
|
if(fail != null)
|
||||||
|
return "Failure recovery object";
|
||||||
|
else
|
||||||
|
return result + " is good";
|
||||||
|
})
|
||||||
|
.thenAccept(str ->
|
||||||
|
System.out.println("result: " + str));
|
||||||
|
|
||||||
|
// Do something but pass the same result through:
|
||||||
|
CompletableExceptions
|
||||||
|
.test("whenComplete", failcount)
|
||||||
|
.whenComplete((result, fail) -> { // BiConsumer
|
||||||
|
if(fail != null)
|
||||||
|
System.out.println("It failed");
|
||||||
|
else
|
||||||
|
System.out.println(result + " OK");
|
||||||
|
})
|
||||||
|
.thenAccept(r ->
|
||||||
|
System.out.println("result: " + r));
|
||||||
|
}
|
||||||
|
public static void main(String[] args) {
|
||||||
|
System.out.println("**** Failure Mode ****");
|
||||||
|
handleException(2);
|
||||||
|
System.out.println("**** Success Mode ****");
|
||||||
|
handleException(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Output:
|
||||||
|
**** Failure Mode ****
|
||||||
|
Breakable_exceptionally [1]
|
||||||
|
result: Breakable_java.lang.RuntimeException:
|
||||||
|
Breakable_exceptionally failed [0]
|
||||||
|
Breakable_handle [1]
|
||||||
|
result: Failure recovery object
|
||||||
|
Breakable_whenComplete [1]
|
||||||
|
It failed
|
||||||
|
**** Success Mode ****
|
||||||
|
Breakable_exceptionally [-1]
|
||||||
|
Breakable_exceptionally [-2]
|
||||||
|
Breakable_exceptionally [-3]
|
||||||
|
Breakable_exceptionally [-4]
|
||||||
|
result: Breakable_exceptionally [-4]
|
||||||
|
Breakable_handle [-1]
|
||||||
|
Breakable_handle [-2]
|
||||||
|
Breakable_handle [-3]
|
||||||
|
Breakable_handle [-4]
|
||||||
|
result: Breakable_handle [-4] is good
|
||||||
|
Breakable_whenComplete [-1]
|
||||||
|
Breakable_whenComplete [-2]
|
||||||
|
Breakable_whenComplete [-3]
|
||||||
|
Breakable_whenComplete [-4]
|
||||||
|
Breakable_whenComplete [-4] OK
|
||||||
|
result: Breakable_whenComplete [-4]
|
||||||
|
*/
|
@ -1,19 +0,0 @@
|
|||||||
// concurrent/Chopstick.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.
|
|
||||||
// Chopsticks for dining philosophers
|
|
||||||
|
|
||||||
public class Chopstick {
|
|
||||||
private boolean taken = false;
|
|
||||||
public synchronized
|
|
||||||
void take() throws InterruptedException {
|
|
||||||
while(taken)
|
|
||||||
wait();
|
|
||||||
taken = true;
|
|
||||||
}
|
|
||||||
public synchronized void drop() {
|
|
||||||
taken = false;
|
|
||||||
notifyAll();
|
|
||||||
}
|
|
||||||
}
|
|
@ -19,3 +19,9 @@ public class CompletableApply {
|
|||||||
cf4.thenApply(Machina::work);
|
cf4.thenApply(Machina::work);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Output:
|
||||||
|
Machina0: ONE
|
||||||
|
Machina0: TWO
|
||||||
|
Machina0: THREE
|
||||||
|
Machina0: complete
|
||||||
|
*/
|
||||||
|
69
concurrent/CompletableExceptions.java
Normal file
69
concurrent/CompletableExceptions.java
Normal file
@ -0,0 +1,69 @@
|
|||||||
|
// concurrent/CompletableExceptions.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 onjava.Nap;
|
||||||
|
|
||||||
|
public class CompletableExceptions {
|
||||||
|
static CompletableFuture<Breakable>
|
||||||
|
test(String id, int failcount) {
|
||||||
|
return
|
||||||
|
CompletableFuture.completedFuture(
|
||||||
|
new Breakable(id, failcount))
|
||||||
|
.thenApply(Breakable::work)
|
||||||
|
.thenApply(Breakable::work)
|
||||||
|
.thenApply(Breakable::work)
|
||||||
|
.thenApply(Breakable::work);
|
||||||
|
}
|
||||||
|
public static void main(String[] args) {
|
||||||
|
// Exceptions don't appear ...
|
||||||
|
test("A", 1);
|
||||||
|
test("B", 2);
|
||||||
|
test("C", 3);
|
||||||
|
test("D", 4);
|
||||||
|
test("E", 5);
|
||||||
|
// ... until you try to fetch the value:
|
||||||
|
try {
|
||||||
|
test("F", 2).get(); // or join()
|
||||||
|
} catch(Exception e) {
|
||||||
|
System.out.println(e.getMessage());
|
||||||
|
}
|
||||||
|
// Test for exceptions:
|
||||||
|
System.out.println(
|
||||||
|
test("G", 2).isCompletedExceptionally());
|
||||||
|
// Counts as "done":
|
||||||
|
System.out.println(test("H", 2).isDone());
|
||||||
|
// Force an exception:
|
||||||
|
CompletableFuture<Integer> cfi =
|
||||||
|
new CompletableFuture<>();
|
||||||
|
System.out.println("done? " + cfi.isDone());
|
||||||
|
cfi.completeExceptionally(
|
||||||
|
new RuntimeException("forced"));
|
||||||
|
try {
|
||||||
|
cfi.get();
|
||||||
|
} catch(Exception e) {
|
||||||
|
System.out.println(e.getMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* Output:
|
||||||
|
Breakable_B [1]
|
||||||
|
Breakable_C [2]
|
||||||
|
Breakable_C [1]
|
||||||
|
Breakable_D [3]
|
||||||
|
Breakable_D [2]
|
||||||
|
Breakable_D [1]
|
||||||
|
Breakable_E [4]
|
||||||
|
Breakable_E [3]
|
||||||
|
Breakable_E [2]
|
||||||
|
Breakable_E [1]
|
||||||
|
Breakable_F [1]
|
||||||
|
java.lang.RuntimeException: Breakable_F failed
|
||||||
|
Breakable_G [1]
|
||||||
|
true
|
||||||
|
Breakable_H [1]
|
||||||
|
true
|
||||||
|
done? false
|
||||||
|
java.lang.RuntimeException: forced
|
||||||
|
*/
|
@ -5,10 +5,10 @@
|
|||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
public class CompletableOperations {
|
public class CompletableOperations {
|
||||||
static CompletableFuture<Integer> cfi() {
|
static CompletableFuture<Integer> cfi(int i) {
|
||||||
return
|
return
|
||||||
CompletableFuture.completedFuture(
|
CompletableFuture.completedFuture(
|
||||||
new Integer(1));
|
new Integer(i));
|
||||||
}
|
}
|
||||||
// Get and show value stored in a CF:
|
// Get and show value stored in a CF:
|
||||||
static void showr(CompletableFuture<Integer> c) {
|
static void showr(CompletableFuture<Integer> c) {
|
||||||
@ -29,11 +29,60 @@ public class CompletableOperations {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
showr(cfi()); // Basic test
|
showr(cfi(1)); // Basic test
|
||||||
showr(cfi().thenApplyAsync(i -> i + 42));
|
voidr(cfi(2).runAsync(() ->
|
||||||
voidr(cfi().runAsync(() -> System.out.println("run")));
|
System.out.println("runAsync")));
|
||||||
CompletableFuture<Integer> c = cfi();
|
voidr(cfi(3).thenRunAsync(() ->
|
||||||
|
System.out.println("thenRunAsync")));
|
||||||
|
showr(CompletableFuture.supplyAsync(() -> 99));
|
||||||
|
voidr(cfi(4).thenAcceptAsync(i ->
|
||||||
|
System.out.println("thenAcceptAsync: " + i)));
|
||||||
|
showr(cfi(5).thenApplyAsync(i -> i + 42));
|
||||||
|
showr(cfi(6).thenComposeAsync(i -> cfi(i + 99)));
|
||||||
|
CompletableFuture<Integer> c = cfi(7);
|
||||||
c.obtrudeValue(111);
|
c.obtrudeValue(111);
|
||||||
showr(c);
|
showr(c);
|
||||||
|
showr(cfi(8).toCompletableFuture());
|
||||||
|
c = new CompletableFuture<>();
|
||||||
|
c.complete(9);
|
||||||
|
showr(c);
|
||||||
|
c = new CompletableFuture<>();
|
||||||
|
c.cancel(true);
|
||||||
|
System.out.println("cancelled: " +
|
||||||
|
c.isCancelled());
|
||||||
|
System.out.println("completed exceptionally: " +
|
||||||
|
c.isCompletedExceptionally());
|
||||||
|
System.out.println("done: " + c.isDone());
|
||||||
|
System.out.println(c);
|
||||||
|
c = new CompletableFuture<>();
|
||||||
|
System.out.println(c.getNow(777));
|
||||||
|
c = new CompletableFuture<>();
|
||||||
|
c.thenApplyAsync(i -> i + 42)
|
||||||
|
.thenApplyAsync(i -> i * 12);
|
||||||
|
System.out.println("dependents: " +
|
||||||
|
c.getNumberOfDependents());
|
||||||
|
c.thenApplyAsync(i -> i / 2);
|
||||||
|
System.out.println("dependents: " +
|
||||||
|
c.getNumberOfDependents());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Output:
|
||||||
|
1
|
||||||
|
runAsync
|
||||||
|
thenRunAsync
|
||||||
|
99
|
||||||
|
thenAcceptAsync: 4
|
||||||
|
47
|
||||||
|
105
|
||||||
|
111
|
||||||
|
8
|
||||||
|
9
|
||||||
|
cancelled: true
|
||||||
|
completed exceptionally: true
|
||||||
|
done: true
|
||||||
|
java.util.concurrent.CompletableFuture@404b9385[Completed
|
||||||
|
exceptionally]
|
||||||
|
777
|
||||||
|
dependents: 1
|
||||||
|
dependents: 2
|
||||||
|
*/
|
||||||
|
@ -42,4 +42,47 @@ public class CompletablePizza {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Output:
|
/* Output:
|
||||||
|
/* Output:
|
||||||
|
56
|
||||||
|
Pizza 0: ROLLED
|
||||||
|
Pizza 1: ROLLED
|
||||||
|
Pizza 4: ROLLED
|
||||||
|
Pizza 2: ROLLED
|
||||||
|
Pizza 3: ROLLED
|
||||||
|
Pizza 0: SAUCED
|
||||||
|
Pizza 3: SAUCED
|
||||||
|
Pizza 2: SAUCED
|
||||||
|
Pizza 4: SAUCED
|
||||||
|
Pizza 1: SAUCED
|
||||||
|
Pizza 0: CHEESED
|
||||||
|
Pizza 4: CHEESED
|
||||||
|
Pizza 2: CHEESED
|
||||||
|
Pizza 3: CHEESED
|
||||||
|
Pizza 1: CHEESED
|
||||||
|
Pizza 0: TOPPED
|
||||||
|
Pizza 4: TOPPED
|
||||||
|
Pizza 1: TOPPED
|
||||||
|
Pizza 3: TOPPED
|
||||||
|
Pizza 2: TOPPED
|
||||||
|
Pizza 0: BAKED
|
||||||
|
Pizza 4: BAKED
|
||||||
|
Pizza 3: BAKED
|
||||||
|
Pizza 1: BAKED
|
||||||
|
Pizza 2: BAKED
|
||||||
|
Pizza 0: SLICED
|
||||||
|
Pizza 2: SLICED
|
||||||
|
Pizza 4: SLICED
|
||||||
|
Pizza 1: SLICED
|
||||||
|
Pizza 3: SLICED
|
||||||
|
Pizza 0: BOXED
|
||||||
|
Pizza0: complete
|
||||||
|
Pizza 4: BOXED
|
||||||
|
Pizza 3: BOXED
|
||||||
|
Pizza 2: BOXED
|
||||||
|
Pizza 1: BOXED
|
||||||
|
Pizza1: complete
|
||||||
|
Pizza2: complete
|
||||||
|
Pizza3: complete
|
||||||
|
Pizza4: complete
|
||||||
|
1659
|
||||||
*/
|
*/
|
||||||
|
@ -1,60 +0,0 @@
|
|||||||
// concurrent/DeadlockingDiningPhilosophers.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.
|
|
||||||
// Demonstrates how deadlock can be hidden in a program
|
|
||||||
// {java DeadlockingDiningPhilosophers 0 5 timeout}
|
|
||||||
import java.util.concurrent.*;
|
|
||||||
import onjava.Nap;
|
|
||||||
|
|
||||||
public class DeadlockingDiningPhilosophers {
|
|
||||||
public static void main(String[] args) {
|
|
||||||
int ponder = 5;
|
|
||||||
if(args.length > 0)
|
|
||||||
ponder = Integer.parseInt(args[0]);
|
|
||||||
int size = 5;
|
|
||||||
if(args.length > 1)
|
|
||||||
size = Integer.parseInt(args[1]);
|
|
||||||
ExecutorService es = Executors.newCachedThreadPool();
|
|
||||||
Chopstick[] sticks = new Chopstick[size];
|
|
||||||
for(int i = 0; i < size; i++)
|
|
||||||
sticks[i] = new Chopstick();
|
|
||||||
for(int i = 0; i < size; i++)
|
|
||||||
es.execute(new Philosopher(
|
|
||||||
sticks[i], sticks[(i+1) % size], i, ponder));
|
|
||||||
if(args.length == 3 && args[2].equals("timeout"))
|
|
||||||
new Nap(5000);
|
|
||||||
else {
|
|
||||||
System.out.println("Press 'Enter' to quit");
|
|
||||||
try {
|
|
||||||
System.in.read();
|
|
||||||
} catch(Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
es.shutdownNow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Output: (First and Last 10 Lines)
|
|
||||||
Philosopher 0 thinking
|
|
||||||
Philosopher 4 thinking
|
|
||||||
Philosopher 1 thinking
|
|
||||||
Philosopher 3 thinking
|
|
||||||
Philosopher 2 thinking
|
|
||||||
Philosopher 3 grabbing right
|
|
||||||
Philosopher 1 grabbing right
|
|
||||||
Philosopher 4 grabbing right
|
|
||||||
Philosopher 0 grabbing right
|
|
||||||
Philosopher 4 grabbing left
|
|
||||||
...________...________...________...________...
|
|
||||||
Philosopher 3 grabbing left
|
|
||||||
Philosopher 1 grabbing left
|
|
||||||
Philosopher 4 grabbing left
|
|
||||||
Philosopher 2 grabbing left
|
|
||||||
Philosopher 0 grabbing left
|
|
||||||
Philosopher 1 exiting via interrupt
|
|
||||||
Philosopher 4 exiting via interrupt
|
|
||||||
Philosopher 3 exiting via interrupt
|
|
||||||
Philosopher 2 exiting via interrupt
|
|
||||||
Philosopher 0 exiting via interrupt
|
|
||||||
*/
|
|
64
concurrent/DiningPhilosophers.java
Normal file
64
concurrent/DiningPhilosophers.java
Normal file
@ -0,0 +1,64 @@
|
|||||||
|
// concurrent/DiningPhilosophers.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.
|
||||||
|
// Deadlock can be hidden in a program
|
||||||
|
import java.util.stream.*;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import static java.util.concurrent.TimeUnit.*;
|
||||||
|
|
||||||
|
public class DiningPhilosophers {
|
||||||
|
static void stopAfter(int secs) {
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* 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
|
||||||
|
*/
|
@ -5,42 +5,108 @@
|
|||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
public class DualCompletableOperations {
|
public class DualCompletableOperations {
|
||||||
static
|
static CompletableFuture<Workable> cfA, cfB;
|
||||||
CompletableFuture<RandomWork> makeCF(int id) {
|
|
||||||
return
|
|
||||||
CompletableFuture.completedFuture(
|
|
||||||
new RandomWork(id))
|
|
||||||
.thenApplyAsync(RandomWork::work);
|
|
||||||
}
|
|
||||||
static CompletableFuture<RandomWork> cfA, cfB;
|
|
||||||
static int count = 0;
|
|
||||||
static void init() {
|
static void init() {
|
||||||
cfA = makeCF(count++);
|
cfA = Workable.make("A", 150);
|
||||||
cfB = makeCF(count++);
|
cfB = Workable.make("B", 100); // Always wins
|
||||||
}
|
}
|
||||||
static void join() {
|
static void join() {
|
||||||
cfA.join();
|
cfA.join();
|
||||||
cfB.join();
|
cfB.join();
|
||||||
|
System.out.println("*****************");
|
||||||
}
|
}
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
init();
|
|
||||||
cfA.runAfterBothAsync(cfB, () ->
|
|
||||||
System.out.println("Completed Both"));
|
|
||||||
join();
|
|
||||||
|
|
||||||
init();
|
init();
|
||||||
cfA.runAfterEitherAsync(cfB, () ->
|
cfA.runAfterEitherAsync(cfB, () ->
|
||||||
System.out.println("Completed Either"));
|
System.out.println("runAfterEither"));
|
||||||
join();
|
join();
|
||||||
|
|
||||||
init();
|
init();
|
||||||
cfA.applyToEitherAsync(cfB, rw -> {
|
cfA.runAfterBothAsync(cfB, () ->
|
||||||
System.out.println("applyToEither: " + rw);
|
System.out.println("runAfterBoth"));
|
||||||
return rw;
|
join();
|
||||||
|
|
||||||
|
init();
|
||||||
|
cfA.applyToEitherAsync(cfB, w -> {
|
||||||
|
System.out.println("applyToEither: " + w);
|
||||||
|
return w;
|
||||||
});
|
});
|
||||||
join();
|
join();
|
||||||
|
|
||||||
|
init();
|
||||||
|
cfA.acceptEitherAsync(cfB, w -> {
|
||||||
|
System.out.println("acceptEither: " + w);
|
||||||
|
});
|
||||||
|
join();
|
||||||
|
|
||||||
|
init();
|
||||||
|
cfA.thenAcceptBothAsync(cfB, (w1, w2) -> {
|
||||||
|
System.out.println("thenAcceptBoth: "
|
||||||
|
+ w1 + ", " + w2);
|
||||||
|
});
|
||||||
|
join();
|
||||||
|
|
||||||
|
init();
|
||||||
|
cfA.thenCombineAsync(cfB, (w1, w2) -> {
|
||||||
|
System.out.println("thenCombine: "
|
||||||
|
+ w1 + ", " + w2);
|
||||||
|
return w1;
|
||||||
|
});
|
||||||
|
join();
|
||||||
|
|
||||||
|
init();
|
||||||
|
CompletableFuture<Workable>
|
||||||
|
cfC = Workable.make("C", 75),
|
||||||
|
cfD = Workable.make("D", 99);
|
||||||
|
CompletableFuture.anyOf(cfA, cfB, cfC, cfD)
|
||||||
|
.thenRunAsync(() ->
|
||||||
|
System.out.println("anyOf"));
|
||||||
|
join();
|
||||||
|
|
||||||
|
init();
|
||||||
|
cfC = Workable.make("C", 75);
|
||||||
|
cfD = Workable.make("D", 99);
|
||||||
|
CompletableFuture.allOf(cfA, cfB, cfC, cfD)
|
||||||
|
.thenRunAsync(() ->
|
||||||
|
System.out.println("allOf"));
|
||||||
|
join();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Output:
|
/* Output:
|
||||||
|
Workable[BW]
|
||||||
|
runAfterEither
|
||||||
|
Workable[AW]
|
||||||
|
*****************
|
||||||
|
Workable[BW]
|
||||||
|
Workable[AW]
|
||||||
|
*****************
|
||||||
|
runAfterBoth
|
||||||
|
Workable[BW]
|
||||||
|
applyToEither: Workable[BW]
|
||||||
|
Workable[AW]
|
||||||
|
*****************
|
||||||
|
Workable[BW]
|
||||||
|
acceptEither: Workable[BW]
|
||||||
|
Workable[AW]
|
||||||
|
*****************
|
||||||
|
Workable[BW]
|
||||||
|
Workable[AW]
|
||||||
|
*****************
|
||||||
|
thenAcceptBoth: Workable[AW], Workable[BW]
|
||||||
|
Workable[BW]
|
||||||
|
Workable[AW]
|
||||||
|
*****************
|
||||||
|
thenCombine: Workable[AW], Workable[BW]
|
||||||
|
Workable[CW]
|
||||||
|
anyOf
|
||||||
|
Workable[DW]
|
||||||
|
Workable[BW]
|
||||||
|
Workable[AW]
|
||||||
|
*****************
|
||||||
|
Workable[CW]
|
||||||
|
Workable[DW]
|
||||||
|
Workable[BW]
|
||||||
|
Workable[AW]
|
||||||
|
*****************
|
||||||
|
allOf
|
||||||
*/
|
*/
|
||||||
|
@ -1,65 +0,0 @@
|
|||||||
// concurrent/FixedDiningPhilosophers.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.
|
|
||||||
// Dining philosophers without deadlock
|
|
||||||
// {java FixedDiningPhilosophers 5 5 timeout}
|
|
||||||
import java.util.concurrent.*;
|
|
||||||
import onjava.Nap;
|
|
||||||
|
|
||||||
public class FixedDiningPhilosophers {
|
|
||||||
public static void
|
|
||||||
main(String[] args) {
|
|
||||||
int ponder = 5;
|
|
||||||
if(args.length > 0)
|
|
||||||
ponder = Integer.parseInt(args[0]);
|
|
||||||
int size = 5;
|
|
||||||
if(args.length > 1)
|
|
||||||
size = Integer.parseInt(args[1]);
|
|
||||||
ExecutorService es = Executors.newCachedThreadPool();
|
|
||||||
Chopstick[] sticks = new Chopstick[size];
|
|
||||||
for(int i = 0; i < size; i++)
|
|
||||||
sticks[i] = new Chopstick();
|
|
||||||
for(int i = 0; i < size; i++)
|
|
||||||
if(i < (size-1))
|
|
||||||
es.execute(new Philosopher(
|
|
||||||
sticks[i], sticks[i+1], i, ponder));
|
|
||||||
else
|
|
||||||
es.execute(new Philosopher(
|
|
||||||
sticks[0], sticks[i], i, ponder));
|
|
||||||
if(args.length == 3 && args[2].equals("timeout"))
|
|
||||||
new Nap(5000);
|
|
||||||
else {
|
|
||||||
System.out.println("Press 'Enter' to quit");
|
|
||||||
try {
|
|
||||||
System.in.read();
|
|
||||||
} catch(Exception e) {
|
|
||||||
throw new RuntimeException(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
es.shutdownNow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
/* Output: (First and Last 10 Lines)
|
|
||||||
Philosopher 1 thinking
|
|
||||||
Philosopher 4 thinking
|
|
||||||
Philosopher 2 thinking
|
|
||||||
Philosopher 0 thinking
|
|
||||||
Philosopher 3 thinking
|
|
||||||
Philosopher 1 grabbing right
|
|
||||||
Philosopher 2 grabbing right
|
|
||||||
Philosopher 4 grabbing right
|
|
||||||
Philosopher 4 grabbing left
|
|
||||||
Philosopher 4 eating
|
|
||||||
...________...________...________...________...
|
|
||||||
Philosopher 1 thinking
|
|
||||||
Philosopher 0 grabbing left
|
|
||||||
Philosopher 0 eating
|
|
||||||
Philosopher 2 eating
|
|
||||||
Philosopher 1 grabbing right
|
|
||||||
Philosopher 3 exiting via interrupt
|
|
||||||
Philosopher 1 exiting via interrupt
|
|
||||||
Philosopher 2 exiting via interrupt
|
|
||||||
Philosopher 0 exiting via interrupt
|
|
||||||
Philosopher 4 exiting via interrupt
|
|
||||||
*/
|
|
31
concurrent/FrostedCake.java
Normal file
31
concurrent/FrostedCake.java
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
// concurrent/FrostedCake.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.function.*;
|
||||||
|
import java.util.stream.*;
|
||||||
|
import onjava.Nap;
|
||||||
|
|
||||||
|
class Frosting {
|
||||||
|
private Frosting() {}
|
||||||
|
static CompletableFuture<Frosting> make() {
|
||||||
|
new Nap(100);
|
||||||
|
return CompletableFuture
|
||||||
|
.completedFuture(new Frosting());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public class FrostedCake {
|
||||||
|
public FrostedCake(Baked baked, Frosting frosting) {
|
||||||
|
new Nap(100);
|
||||||
|
}
|
||||||
|
public static void main(String[] args) {
|
||||||
|
Baked.batch().forEach(baked -> baked
|
||||||
|
.thenCombineAsync(Frosting.make(),
|
||||||
|
(cake, frosting) ->
|
||||||
|
new FrostedCake(cake, frosting))
|
||||||
|
.thenAcceptAsync(System.out::println).join());
|
||||||
|
// Need to rewrite...
|
||||||
|
}
|
||||||
|
}
|
@ -31,3 +31,7 @@ public class ParallelPrime {
|
|||||||
StandardOpenOption.CREATE);
|
StandardOpenOption.CREATE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Output:
|
||||||
|
/* Output:
|
||||||
|
616
|
||||||
|
*/
|
||||||
|
@ -23,3 +23,6 @@ public class ParallelStreamPuzzle {
|
|||||||
System.out.println(x);
|
System.out.println(x);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Output:
|
||||||
|
[2, 8, 21, 24, 27, 30, 33, 37, 40, 43]
|
||||||
|
*/
|
||||||
|
@ -2,48 +2,58 @@
|
|||||||
// (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.
|
||||||
// A dining philosopher
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import onjava.Nap;
|
import java.util.stream.*;
|
||||||
|
import java.util.concurrent.*;
|
||||||
|
import static java.util.concurrent.TimeUnit.*;
|
||||||
|
import java.util.concurrent.atomic.*;
|
||||||
|
|
||||||
public class Philosopher implements Runnable {
|
class Philosopher implements Runnable {
|
||||||
private Chopstick left;
|
static class Chopstick {}
|
||||||
private Chopstick right;
|
public static final int QUANTITY = 5;
|
||||||
private final int id;
|
static Queue<String> trace =
|
||||||
private final int ponderFactor;
|
new ConcurrentLinkedQueue<>();
|
||||||
private SplittableRandom rand = new SplittableRandom(47);
|
static AtomicBoolean running =
|
||||||
private void pause() {
|
new AtomicBoolean(true);
|
||||||
if(ponderFactor == 0) return;
|
public static
|
||||||
new Nap(rand.nextInt(ponderFactor * 250));
|
List<BlockingQueue<Chopstick>> chopsticks =
|
||||||
}
|
IntStream.range(0, Philosopher.QUANTITY)
|
||||||
public Philosopher(Chopstick left, Chopstick right,
|
.mapToObj(i -> {
|
||||||
int ident, int ponder) {
|
BlockingQueue<Chopstick> bd =
|
||||||
this.left = left;
|
new ArrayBlockingQueue<>(1);
|
||||||
this.right = right;
|
bd.add(new Chopstick());
|
||||||
id = ident;
|
return bd;
|
||||||
ponderFactor = ponder;
|
})
|
||||||
|
.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
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
while(!Thread.interrupted()) {
|
while(running.get()) {
|
||||||
System.out.println(this + " " + "thinking");
|
trace.add(this + " thinking");
|
||||||
pause();
|
|
||||||
// Philosopher becomes hungry
|
// Philosopher becomes hungry
|
||||||
System.out.println(this + " " + "grabbing right");
|
trace.add(this + " grabbing right");
|
||||||
right.take();
|
Chopstick rightStick =
|
||||||
System.out.println(this + " " + "grabbing left");
|
chopsticks.get(right).poll(2, SECONDS);
|
||||||
left.take();
|
trace.add(this + " grabbing left");
|
||||||
System.out.println(this + " " + "eating");
|
Chopstick leftStick =
|
||||||
pause();
|
chopsticks.get(left).poll(2, SECONDS);
|
||||||
right.drop();
|
trace.add(this + " eating");
|
||||||
left.drop();
|
// Finished, return chopsticks to table:
|
||||||
|
chopsticks.get(right).put(rightStick);
|
||||||
|
chopsticks.get(left).put(leftStick);
|
||||||
}
|
}
|
||||||
} catch(InterruptedException e) {
|
} catch(InterruptedException e) {
|
||||||
System.out.println(
|
trace.add("exiting via interrupt");
|
||||||
this + " " + "exiting via interrupt");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString() { return "Philosopher " + id; }
|
public String toString() {
|
||||||
|
return "P" + seatNumber;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -22,3 +22,14 @@ public class QuittingTasks {
|
|||||||
es.shutdown();
|
es.shutdown();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Output:
|
||||||
|
125 148 115 127 120 118 106 140 77 119 97 80 143 17 92 147
|
||||||
|
89 123 16 12 138 25 13 101 135 96 76 73 130 133 37 132 134
|
||||||
|
149 137 122 29 49 60 40 142 131 53 1 98 145 126 65 5 64 82
|
||||||
|
79 68 86 141 61 128 22 7 26 19 139 114 146 14 15 43 34 10
|
||||||
|
75 87 90 31 47 38 62 18 63 41 42 144 66 23 6 4 91 70 83 102
|
||||||
|
103 54 69 74 56 71 94 88 78 81 57 52 93 45 48 44 32 28 36
|
||||||
|
33 104 105 112 109 100 117 24 108 21 116 20 9 85 8 84 72
|
||||||
|
107 113 121 124 136 129 99 95 55 3 27 2 59 67 50 58 51 39
|
||||||
|
30 35 46 110 111 11
|
||||||
|
*/
|
||||||
|
@ -1,22 +0,0 @@
|
|||||||
// concurrent/RandomWork.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 onjava.Nap;
|
|
||||||
|
|
||||||
public class RandomWork {
|
|
||||||
private static SplittableRandom rand =
|
|
||||||
new SplittableRandom(47);
|
|
||||||
private final int id;
|
|
||||||
public RandomWork(int id) { this.id = id; }
|
|
||||||
public static RandomWork work(RandomWork r) {
|
|
||||||
new Nap(rand.nextInt(250));
|
|
||||||
System.out.println(r);
|
|
||||||
return r;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public String toString() {
|
|
||||||
return "RandomWork " + id;
|
|
||||||
}
|
|
||||||
}
|
|
@ -36,8 +36,8 @@ public class Summing2 {
|
|||||||
}
|
}
|
||||||
/* Output:
|
/* Output:
|
||||||
200000010000000
|
200000010000000
|
||||||
Array Stream Sum: 112ms
|
Array Stream Sum: 22ms
|
||||||
Parallel: 28ms
|
Parallel: 21ms
|
||||||
Basic Sum: 33ms
|
Basic Sum: 16ms
|
||||||
parallelPrefix: 60ms
|
parallelPrefix: 116ms
|
||||||
*/
|
*/
|
||||||
|
32
concurrent/Workable.java
Normal file
32
concurrent/Workable.java
Normal file
@ -0,0 +1,32 @@
|
|||||||
|
// concurrent/Workable.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 onjava.Nap;
|
||||||
|
|
||||||
|
public class Workable {
|
||||||
|
String id;
|
||||||
|
final int duration;
|
||||||
|
public Workable(String id, int duration) {
|
||||||
|
this.id = id;
|
||||||
|
this.duration = duration;
|
||||||
|
}
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "Workable[" + id + "]";
|
||||||
|
}
|
||||||
|
public static Workable work(Workable tt) {
|
||||||
|
new Nap(tt.duration); // Milliseconds
|
||||||
|
tt.id = tt.id + "W";
|
||||||
|
System.out.println(tt);
|
||||||
|
return tt;
|
||||||
|
}
|
||||||
|
public static CompletableFuture<Workable>
|
||||||
|
make(String id, int duration) {
|
||||||
|
return
|
||||||
|
CompletableFuture.completedFuture(
|
||||||
|
new Workable(id, duration))
|
||||||
|
.thenApplyAsync(Workable::work);
|
||||||
|
}
|
||||||
|
}
|
@ -14,7 +14,7 @@ project(':understandingcollections') {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
project(':concurrent') {
|
project(':lowlevel') {
|
||||||
dependencies {
|
dependencies {
|
||||||
compile project(':enums')
|
compile project(':enums')
|
||||||
}
|
}
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
// concurrent/BankTellerSimulation.java
|
// lowlevel/BankTellerSimulation.java
|
||||||
// (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.
|
@ -1,4 +1,4 @@
|
|||||||
// concurrent/CarBuilder.java
|
// lowlevel/CarBuilder.java
|
||||||
// (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.
|
@ -1,4 +1,4 @@
|
|||||||
// concurrent/Restaurant.java
|
// lowlevel/Restaurant.java
|
||||||
// (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.
|
@ -1,4 +1,4 @@
|
|||||||
// concurrent/ToastOMatic.java
|
// lowlevel/ToastOMatic.java
|
||||||
// (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.
|
@ -1,4 +1,4 @@
|
|||||||
// concurrent/restaurant2/RestaurantWithQueues.java
|
// lowlevel/restaurant2/RestaurantWithQueues.java
|
||||||
// (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.
|
Loading…
x
Reference in New Issue
Block a user