Appendix rewrites
This commit is contained in:
parent
bc786ef438
commit
737320b37b
@ -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.
|
||||||
// Atomic classes are occasionally useful in regular code
|
// Atomic classes are occasionally useful in regular code
|
||||||
// {IgnoreOutput} // No output validation
|
|
||||||
import java.util.concurrent.atomic.*;
|
import java.util.concurrent.atomic.*;
|
||||||
|
|
||||||
public class AtomicEvenProducer extends IntGenerator {
|
public class AtomicEvenProducer extends IntGenerator {
|
||||||
@ -17,3 +16,6 @@ public class AtomicEvenProducer extends IntGenerator {
|
|||||||
EvenChecker.test(new AtomicEvenProducer());
|
EvenChecker.test(new AtomicEvenProducer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Output:
|
||||||
|
No odd numbers discovered
|
||||||
|
*/
|
||||||
|
@ -17,11 +17,9 @@ public class AtomicIntegerTest implements Runnable {
|
|||||||
evenIncrement();
|
evenIncrement();
|
||||||
}
|
}
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
new TimedAbort(5); // Terminate after 5 seconds
|
new TimedAbort(4, "No failures discovered");
|
||||||
ExecutorService exec =
|
|
||||||
Executors.newCachedThreadPool();
|
|
||||||
AtomicIntegerTest ait = new AtomicIntegerTest();
|
AtomicIntegerTest ait = new AtomicIntegerTest();
|
||||||
exec.execute(ait);
|
CompletableFuture.runAsync(ait);
|
||||||
while(true) {
|
while(true) {
|
||||||
int val = ait.getValue();
|
int val = ait.getValue();
|
||||||
if(val % 2 != 0) {
|
if(val % 2 != 0) {
|
||||||
@ -32,5 +30,5 @@ public class AtomicIntegerTest implements Runnable {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Output:
|
/* Output:
|
||||||
TimedAbort 5
|
No failures discovered
|
||||||
*/
|
*/
|
||||||
|
@ -13,12 +13,14 @@ public class Atomicity {
|
|||||||
Compiled from "Atomicity.java"
|
Compiled from "Atomicity.java"
|
||||||
public class Atomicity {
|
public class Atomicity {
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
public Atomicity();
|
public Atomicity();
|
||||||
Code:
|
Code:
|
||||||
0: aload_0
|
0: aload_0
|
||||||
1: invokespecial #1 // Method
|
1: invokespecial #1 // Method
|
||||||
java/lang/Object."<init>":()V
|
java/lang/Object."<init>":()V
|
||||||
4: return
|
4: return
|
||||||
|
|
||||||
void f1();
|
void f1();
|
||||||
Code:
|
Code:
|
||||||
0: aload_0
|
0: aload_0
|
||||||
@ -28,6 +30,7 @@ java/lang/Object."<init>":()V
|
|||||||
6: iadd
|
6: iadd
|
||||||
7: putfield #2 // Field i:I
|
7: putfield #2 // Field i:I
|
||||||
10: return
|
10: return
|
||||||
|
|
||||||
void f2();
|
void f2();
|
||||||
Code:
|
Code:
|
||||||
0: aload_0
|
0: aload_0
|
||||||
|
@ -17,20 +17,18 @@ public class AtomicityTest implements Runnable {
|
|||||||
evenIncrement();
|
evenIncrement();
|
||||||
}
|
}
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
new TimedAbort(4);
|
new TimedAbort(4, "No failures found");
|
||||||
ExecutorService es =
|
|
||||||
Executors.newCachedThreadPool();
|
|
||||||
AtomicityTest at = new AtomicityTest();
|
AtomicityTest at = new AtomicityTest();
|
||||||
es.execute(at);
|
CompletableFuture.runAsync(at);
|
||||||
while(true) {
|
while(true) {
|
||||||
int val = at.getValue();
|
int val = at.getValue();
|
||||||
if(val % 2 != 0) {
|
if(val % 2 != 0) {
|
||||||
System.out.println(val);
|
System.out.println("failed with: " + val);
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Output:
|
/* Output:
|
||||||
1
|
failed with: 21
|
||||||
*/
|
*/
|
||||||
|
@ -38,16 +38,12 @@ public class AttemptLocking {
|
|||||||
final AttemptLocking al = new AttemptLocking();
|
final AttemptLocking al = new AttemptLocking();
|
||||||
al.untimed(); // True -- lock is available
|
al.untimed(); // True -- lock is available
|
||||||
al.timed(); // True -- lock is available
|
al.timed(); // True -- lock is available
|
||||||
// Now create a separate task to grab the lock:
|
// Now create a second task to grab the lock:
|
||||||
new Thread() {
|
CompletableFuture.runAsync( () -> {
|
||||||
{ setDaemon(true); }
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
al.lock.lock();
|
al.lock.lock();
|
||||||
System.out.println("acquired");
|
System.out.println("acquired");
|
||||||
}
|
});
|
||||||
}.start();
|
new Nap(100); // Give the second task a chance
|
||||||
new Nap(10); // Give the 2nd task a chance
|
|
||||||
al.untimed(); // False -- lock grabbed by task
|
al.untimed(); // False -- lock grabbed by task
|
||||||
al.timed(); // False -- lock grabbed by task
|
al.timed(); // False -- lock grabbed by task
|
||||||
}
|
}
|
||||||
@ -55,6 +51,7 @@ public class AttemptLocking {
|
|||||||
/* Output:
|
/* Output:
|
||||||
tryLock(): true
|
tryLock(): true
|
||||||
tryLock(2, TimeUnit.SECONDS): true
|
tryLock(2, TimeUnit.SECONDS): true
|
||||||
tryLock(): true
|
acquired
|
||||||
tryLock(2, TimeUnit.SECONDS): true
|
tryLock(): false
|
||||||
|
tryLock(2, TimeUnit.SECONDS): false
|
||||||
*/
|
*/
|
||||||
|
@ -2,8 +2,9 @@
|
|||||||
// (c)2017 MindView LLC: see Copyright.txt
|
// (c)2017 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.concurrent.*;
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
import java.util.stream.*;
|
||||||
|
import java.util.concurrent.*;
|
||||||
import static java.util.concurrent.TimeUnit.*;
|
import static java.util.concurrent.TimeUnit.*;
|
||||||
|
|
||||||
class DelayedTask implements Runnable, Delayed {
|
class DelayedTask implements Runnable, Delayed {
|
||||||
@ -12,7 +13,7 @@ class DelayedTask implements Runnable, Delayed {
|
|||||||
private final int delta;
|
private final int delta;
|
||||||
private final long trigger;
|
private final long trigger;
|
||||||
protected static List<DelayedTask> sequence =
|
protected static List<DelayedTask> sequence =
|
||||||
new ArrayList<>();
|
new CopyOnWriteArrayList<>();
|
||||||
public DelayedTask(int delayInMilliseconds) {
|
public DelayedTask(int delayInMilliseconds) {
|
||||||
delta = delayInMilliseconds;
|
delta = delayInMilliseconds;
|
||||||
trigger = System.nanoTime() +
|
trigger = System.nanoTime() +
|
||||||
@ -32,74 +33,69 @@ class DelayedTask implements Runnable, Delayed {
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
@Override
|
@Override
|
||||||
public void run() { System.out.print(this + " "); }
|
public void run() {
|
||||||
|
System.out.print(this + " ");
|
||||||
|
}
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return String.format("[%1$-4d]", delta) +
|
return
|
||||||
" Task " + id;
|
String.format("[%d] Task %d", delta, id);
|
||||||
}
|
}
|
||||||
public String summary() {
|
public String summary() {
|
||||||
return "(" + id + ":" + delta + ")";
|
return String.format("(%d:%d)", id, delta);
|
||||||
}
|
|
||||||
public static class EndSentinel extends DelayedTask {
|
|
||||||
private ExecutorService exec;
|
|
||||||
public EndSentinel(int delay, ExecutorService e) {
|
|
||||||
super(delay);
|
|
||||||
exec = e;
|
|
||||||
}
|
}
|
||||||
|
public static class EndTask extends DelayedTask {
|
||||||
|
public EndTask(int delay) { super(delay); }
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
for(DelayedTask pt : sequence) {
|
sequence.forEach(dt ->
|
||||||
System.out.print(pt.summary() + " ");
|
System.out.println(dt.summary() + " "));
|
||||||
}
|
}
|
||||||
System.out.println();
|
|
||||||
System.out.println(this + " Calling shutdownNow()");
|
|
||||||
exec.shutdownNow();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
class DelayedTaskConsumer implements Runnable {
|
|
||||||
private DelayQueue<DelayedTask> q;
|
|
||||||
public DelayedTaskConsumer(DelayQueue<DelayedTask> q) {
|
|
||||||
this.q = q;
|
|
||||||
}
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
while(!Thread.interrupted())
|
|
||||||
q.take().run(); // Run task with current thread
|
|
||||||
} catch(InterruptedException e) {
|
|
||||||
// Acceptable way to exit
|
|
||||||
}
|
|
||||||
System.out.println("Finished DelayedTaskConsumer");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DelayQueueDemo {
|
public class DelayQueueDemo {
|
||||||
public static void main(String[] args) {
|
public static void
|
||||||
SplittableRandom rand = new SplittableRandom(47);
|
main(String[] args) throws Exception {
|
||||||
ExecutorService es = Executors.newCachedThreadPool();
|
DelayQueue<DelayedTask> tasks =
|
||||||
DelayQueue<DelayedTask> queue =
|
Stream.concat(
|
||||||
new DelayQueue<>();
|
// Tasks with random delays:
|
||||||
// Fill with tasks that have random delays:
|
new Random(47).ints(20, 0, 4000)
|
||||||
for(int i = 0; i < 20; i++)
|
.mapToObj(DelayedTask::new),
|
||||||
queue.put(new DelayedTask(rand.nextInt(5000)));
|
// Add the summarizing task:
|
||||||
// Set the stopping point
|
Stream.of(
|
||||||
queue.add(new DelayedTask.EndSentinel(5000, es));
|
new DelayedTask.EndTask(4000)))
|
||||||
es.execute(new DelayedTaskConsumer(queue));
|
.collect(Collectors
|
||||||
|
.toCollection(DelayQueue::new));
|
||||||
|
DelayQueue<DelayedTask> delayQueue =
|
||||||
|
new DelayQueue<>(tasks);
|
||||||
|
while(delayQueue.size() > 0)
|
||||||
|
delayQueue.take().run();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Output:
|
/* Output:
|
||||||
[70 ] Task 10 [125 ] Task 13 [267 ] Task 19 [635 ] Task 0
|
[128] Task 12 [429] Task 6 [551] Task 13 [555] Task 2 [693] Task 3 [809] Task 15
|
||||||
[650 ] Task 16 [682 ] Task 17 [807 ] Task 11 [1131] Task 18
|
[961] Task 5 [1258] Task 1 [1258] Task 20 [1520] Task 19 [1861] Task 4 [1998] T
|
||||||
[1177] Task 4 [1193] Task 9 [1634] Task 15 [1656] Task 6
|
ask 17 [2200] Task 8 [2207] Task 10 [2288] Task 11 [2522] Task 9 [2589] Task 14
|
||||||
[2400] Task 12 [3479] Task 5 [3737] Task 1 [3768] Task 7
|
[2861] Task 18 [2868] Task 7 [3278] Task 16 (0:4000)
|
||||||
[3941] Task 2 [4720] Task 3 [4762] Task 14 [4948] Task 8
|
(1:1258)
|
||||||
(0:635) (1:3737) (2:3941) (3:4720) (4:1177) (5:3479)
|
(2:555)
|
||||||
(6:1656) (7:3768) (8:4948) (9:1193) (10:70) (11:807)
|
(3:693)
|
||||||
(12:2400) (13:125) (14:4762) (15:1634) (16:650) (17:682)
|
(4:1861)
|
||||||
(18:1131) (19:267) (20:5000)
|
(5:961)
|
||||||
[5000] Task 20 Calling shutdownNow()
|
(6:429)
|
||||||
Finished DelayedTaskConsumer
|
(7:2868)
|
||||||
|
(8:2200)
|
||||||
|
(9:2522)
|
||||||
|
(10:2207)
|
||||||
|
(11:2288)
|
||||||
|
(12:128)
|
||||||
|
(13:551)
|
||||||
|
(14:2589)
|
||||||
|
(15:809)
|
||||||
|
(16:3278)
|
||||||
|
(17:1998)
|
||||||
|
(18:2861)
|
||||||
|
(19:1520)
|
||||||
|
(20:1258)
|
||||||
*/
|
*/
|
||||||
|
@ -2,6 +2,8 @@
|
|||||||
// (c)2017 MindView LLC: see Copyright.txt
|
// (c)2017 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 java.util.concurrent.*;
|
||||||
import onjava.TimedAbort;
|
import onjava.TimedAbort;
|
||||||
|
|
||||||
@ -24,15 +26,16 @@ public class EvenChecker implements Runnable {
|
|||||||
}
|
}
|
||||||
// Test any IntGenerator:
|
// Test any IntGenerator:
|
||||||
public static void test(IntGenerator gp, int count) {
|
public static void test(IntGenerator gp, int count) {
|
||||||
System.out.println("Press Control-C to exit");
|
List<CompletableFuture<Void>> checkers =
|
||||||
ExecutorService es = Executors.newCachedThreadPool();
|
IntStream.range(0, count)
|
||||||
for(int i = 0; i < count; i++)
|
.mapToObj(i -> new EvenChecker(gp, i))
|
||||||
es.execute(new EvenChecker(gp, i));
|
.map(CompletableFuture::runAsync)
|
||||||
es.shutdown();
|
.collect(Collectors.toList());
|
||||||
|
checkers.forEach(CompletableFuture::join);
|
||||||
}
|
}
|
||||||
// Default value for count:
|
// Default value for count:
|
||||||
public static void test(IntGenerator gp) {
|
public static void test(IntGenerator gp) {
|
||||||
new TimedAbort(4);
|
new TimedAbort(4, "No odd numbers discovered");
|
||||||
test(gp, 10);
|
test(gp, 10);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,10 @@ public class EvenProducer extends IntGenerator {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Output:
|
/* Output:
|
||||||
Press Control-C to exit
|
1563 not even!
|
||||||
841 not even!
|
1573 not even!
|
||||||
847 not even!
|
1571 not even!
|
||||||
845 not even!
|
1569 not even!
|
||||||
843 not even!
|
1567 not even!
|
||||||
|
1565 not even!
|
||||||
*/
|
*/
|
||||||
|
@ -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.
|
||||||
// Preventing thread collisions with mutexes
|
// Preventing thread collisions with mutexes
|
||||||
// {IgnoreOutput} // No output validation
|
|
||||||
import java.util.concurrent.locks.*;
|
import java.util.concurrent.locks.*;
|
||||||
import onjava.Nap;
|
import onjava.Nap;
|
||||||
|
|
||||||
@ -26,3 +25,6 @@ public class MutexEvenProducer extends IntGenerator {
|
|||||||
EvenChecker.test(new MutexEvenProducer());
|
EvenChecker.test(new MutexEvenProducer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
No odd numbers discovered
|
||||||
|
*/
|
||||||
|
@ -3,43 +3,37 @@
|
|||||||
// 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.
|
||||||
// Operations that might seem safe are not,
|
// Operations that might seem safe are not,
|
||||||
// when threads are present
|
// when threads are present.
|
||||||
// {java SerialNumberChecker 4}
|
import java.util.*;
|
||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
import onjava.Nap;
|
import onjava.Nap;
|
||||||
|
|
||||||
// Reuses storage so we don't run out of memory:
|
// Reuses storage so we don't run out of memory:
|
||||||
class CircularSet {
|
class CircularSet {
|
||||||
private int[] array;
|
private int[] array;
|
||||||
private int len;
|
private int size;
|
||||||
private int index = 0;
|
private int index = 0;
|
||||||
public CircularSet(int size) {
|
public CircularSet(int size) {
|
||||||
array = new int[size];
|
array = new int[size];
|
||||||
len = size;
|
|
||||||
// Initialize to a value not produced
|
// Initialize to a value not produced
|
||||||
// by the SerialNumberSupplier:
|
// by the SerialNumberSupplier:
|
||||||
for(int i = 0; i < size; i++)
|
Arrays.fill(array, -1);
|
||||||
array[i] = -1;
|
this.size = size;
|
||||||
}
|
}
|
||||||
public synchronized void add(int i) {
|
public synchronized void add(int i) {
|
||||||
array[index] = i;
|
array[index] = i;
|
||||||
// Wrap index and write over old elements:
|
// Wrap index and write over old elements:
|
||||||
index = ++index % len;
|
index = ++index % size;
|
||||||
}
|
}
|
||||||
public synchronized boolean contains(int val) {
|
public synchronized boolean contains(int val) {
|
||||||
for(int i = 0; i < len; i++)
|
for(int i = 0; i < size; i++)
|
||||||
if(array[i] == val) return true;
|
if(array[i] == val) return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SerialNumberChecker {
|
public class SerialNumberChecker implements Runnable {
|
||||||
private static final int SIZE = 10;
|
private CircularSet serials = new CircularSet(1000);
|
||||||
private static CircularSet serials =
|
|
||||||
new CircularSet(1000);
|
|
||||||
private static ExecutorService exec =
|
|
||||||
Executors.newCachedThreadPool();
|
|
||||||
static class SerialChecker implements Runnable {
|
|
||||||
@Override
|
@Override
|
||||||
public void run() {
|
public void run() {
|
||||||
while(true) {
|
while(true) {
|
||||||
@ -52,16 +46,11 @@ public class SerialNumberChecker {
|
|||||||
serials.add(serial);
|
serials.add(serial);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
for(int i = 0; i < SIZE; i++)
|
for(int i = 0; i < 10; i++)
|
||||||
exec.execute(new SerialChecker());
|
CompletableFuture.runAsync(
|
||||||
// Stop after n seconds if there's an argument:
|
new SerialNumberChecker());
|
||||||
if(args.length > 0) {
|
new Nap(4000, "No duplicates detected");
|
||||||
new Nap(new Integer(args[0]) * 1000);
|
|
||||||
System.out.println("No duplicates detected");
|
|
||||||
System.exit(0);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Output:
|
/* Output:
|
||||||
|
@ -3,47 +3,39 @@
|
|||||||
// 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.
|
||||||
// Synchronizing on another object
|
// Synchronizing on another object
|
||||||
|
import java.util.concurrent.*;
|
||||||
import onjava.Nap;
|
import onjava.Nap;
|
||||||
|
|
||||||
class DualSynch {
|
class DualSynch {
|
||||||
private Object syncObject = new Object();
|
|
||||||
public synchronized void f() {
|
public synchronized void f() {
|
||||||
for(int i = 0; i < 5; i++) {
|
for(int i = 0; i < 5; i++)
|
||||||
System.out.println("f()");
|
System.out.println("f() " + i);
|
||||||
new Nap(10);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
private Object syncObject = new Object();
|
||||||
public void g() {
|
public void g() {
|
||||||
synchronized(syncObject) {
|
synchronized(syncObject) {
|
||||||
for(int i = 0; i < 5; i++) {
|
for(int i = 0; i < 5; i++)
|
||||||
System.out.println("g()");
|
System.out.println("g() " + i);
|
||||||
new Nap(10);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public class SyncObject {
|
public class SyncObject {
|
||||||
public static void main(String[] args) {
|
public static void main(String[] args) {
|
||||||
final DualSynch ds = new DualSynch();
|
DualSynch ds = new DualSynch();
|
||||||
new Thread() {
|
CompletableFuture.runAsync(() -> ds.f());
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
ds.f();
|
|
||||||
}
|
|
||||||
}.start();
|
|
||||||
ds.g();
|
ds.g();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
/* Output:
|
/* Output:
|
||||||
g()
|
g() 0
|
||||||
g()
|
g() 1
|
||||||
g()
|
f() 0
|
||||||
g()
|
g() 2
|
||||||
g()
|
f() 1
|
||||||
f()
|
g() 3
|
||||||
f()
|
f() 2
|
||||||
f()
|
g() 4
|
||||||
f()
|
f() 3
|
||||||
f()
|
f() 4
|
||||||
*/
|
*/
|
||||||
|
@ -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.
|
||||||
// Simplifying mutexes with the synchronized keyword
|
// Simplifying mutexes with the synchronized keyword
|
||||||
// {IgnoreOutput} // No output validation
|
|
||||||
import onjava.Nap;
|
import onjava.Nap;
|
||||||
|
|
||||||
public class
|
public class
|
||||||
@ -20,3 +19,6 @@ SynchronizedEvenProducer extends IntGenerator {
|
|||||||
EvenChecker.test(new SynchronizedEvenProducer());
|
EvenChecker.test(new SynchronizedEvenProducer());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
/* Output:
|
||||||
|
No odd numbers discovered
|
||||||
|
*/
|
||||||
|
@ -14,4 +14,8 @@ public class Nap {
|
|||||||
throw new RuntimeException(e);
|
throw new RuntimeException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
public Nap(int n, String msg) {
|
||||||
|
this(n);
|
||||||
|
System.out.println(msg);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,11 +7,14 @@ package onjava;
|
|||||||
import java.util.concurrent.*;
|
import java.util.concurrent.*;
|
||||||
|
|
||||||
public class TimedAbort {
|
public class TimedAbort {
|
||||||
public TimedAbort(int n) {
|
public TimedAbort(int n, String msg) {
|
||||||
CompletableFuture.runAsync(() -> {
|
CompletableFuture.runAsync(() -> {
|
||||||
new Nap(1000 * n);
|
new Nap(1000 * n);
|
||||||
System.out.println("TimedAbort " + n);
|
System.out.println(msg);
|
||||||
System.exit(0);
|
System.exit(0);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
public TimedAbort(int n) {
|
||||||
|
this(n, "TimedAbort " + n);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user