$30
This problem set aims to let students explore the different methods provided by the CompletableFuture class in Java 8 or later.
1. Study the given class A below, which uses the methods incr and decr to imitate slow computations.
class A { private final int x;
A() {
this(0);
}
A(int x) { this.x = x;
}
void sleep() {
System.out.println(Thread.currentThread().getName() + " " + x); try {
Thread.sleep(1000);
} catch (InterruptedException e) {
System.out.println("interrupted");
}
}
A incr() {
sleep(); return new A(this.x + 1);
}
A decr() {
sleep();
if (x < 0) {
throw new IllegalStateException();
}
return new A(this.x - 1);
}
public String toString() { return "" + x;
}
}
(a) Suppose we have a method
A foo(A a) {
return a.incr().decr();
}
Convert the method foo above to a method that returns a CompletableFuture so that the body of the method is executed asynchronously. Try different variations by using
i. supplyAsync only;
ii. supplyAsync and thenApply;
iii. supplyAsync and thenApplyAsync
Demonstrate how you would retrieve the result of the computation.
See also: thenRun, thenAccept, runAsync (b) Suppose now we have another method
A bar(A a) {
return a.incr();
}
which we would like to invoke using bar(foo(new A())). Convert the computation within bar to run asynchronously as well. bar should now return a CompletableFuture. In addition, show the equivalent of calling bar(foo(new A())) in an asynchronous fashion, using the method thenCompose. See also: thenCombine
(c) Suppose now we have yet another method
A baz(A a, int x) { if (x == 0) {
return new A(0);
} else {
return a.incr().decr();
}
}
Convert the computation within baz in the else clause to run asynchronously. baz should now return a CompletableFuture. You may find the method completedFuture useful.
(d) Let’s now call foo, bar, baz asynchronously. We would like to output the string "done!" when all three method calls complete. Show how you can use the allOf() method to achieve this behavior.
See also: anyOf, runAfterBoth, runAfterEither.
(e) Calling new A().decr().decr() would cause an exception to be thrown, even when it is done asynchronously. Show how you would use the handle() method to gracefully handle exceptions thrown (such as printing them out) within a chain of CompletableFuture calls.
See also: whenComplete and exceptionally
2. Modify the following sequences of code such that f, g, h and i are now invoked asynchronously, via CompletableFuture. Assume that a has been initialized as
A a = new A();
(a) B b = f(a); C c = g(b);
D d = h(c);
(b) B b = f(a); C c = g(b); h(c); // no return value
(c) B b = f(a); C c = g(b);
D d = h(b);
E e = i(c, d);