Skip to content

Instantly share code, notes, and snippets.

@Tembrel
Created December 18, 2015 17:32
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Tembrel/68d5670bf37824d55078 to your computer and use it in GitHub Desktop.
Save Tembrel/68d5670bf37824d55078 to your computer and use it in GitHub Desktop.
Answer to survey question
/*
* This program takes the code from the survey question, which uses
* CompletableFuture.whenComplete(BiConsumer) and compares it with
* analogous code using CompletableFuture.handle(BiFunction). The only
* difference is the absence of return values in the consumer.
*
* It runs both variants with all different combinations of conditions
* ("true" in the survey question code) to produce the following output:
*
* 1. handle: c1=false, c2=false, result is A
* 2. handle: c1=false, c2=true, result is A
* 3. handle: c1=true, c2=false, result is B
* 4. handle: c1=true, c2=true, exception is SecondException
*
* 5. whenComplete: c1=false, c2=false, result is A
* 6. whenComplete: c1=false, c2=true, result is A
* 7. whenComplete: c1=true, c2=false, exception is FirstException
* 8. whenComplete: c1=true, c2=true, exception is FirstException
*
* I interpret the survey question as being whether the exception
* in line 8 is (I) correct by analogy with line 7, or (II) incorrect
* by analogy with line 4. (In either case, you'd want the suppressed
* exception to be the other exception thrown.)
*
* I vote for the latter case (II), which would require SecondException
* thrown with FirstException suppressed. My argument is that the analogy
* with line 4 is stronger: There are no results involved, so the version
* using BiConsumer should behave like the version using BiFunction.
*/
package net.peierls.example.wcsurvey;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionException;
public class WhenCompleteSurvey {
static class FirstException extends RuntimeException {
}
static class SecondException extends RuntimeException {
}
final boolean c1;
final boolean c2;
WhenCompleteSurvey(boolean c1, boolean c2) {
this.c1 = c1;
this.c2 = c2;
}
void handle(int i) {
CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {
if (c1)
throw new FirstException();
else
return "A";
});
CompletableFuture<String> f2 = f1.handle((result, exception) -> {
if (exception != null) {
if (c2)
throw new SecondException();
else
return "B";
}
else
return result;
});
try {
String result = f2.join();
System.out.printf("%d. handle: c1=%s, c2=%s, result is %s%n", i, c1, c2, result);
} catch (CompletionException e) {
Throwable t = e.getCause();
System.out.printf("%d. handle: c1=%s, c2=%s, exception is %s%n", i, c1, c2, t.getClass().getSimpleName());
}
}
void whenComplete(int i) {
CompletableFuture<String> f1 = CompletableFuture.supplyAsync(() -> {
if (c1)
throw new FirstException();
else
return "A";
});
CompletableFuture<String> f2 = f1.whenComplete((result, exception) -> {
if (exception != null) {
if (c2)
throw new SecondException();
else
return;
}
else
return;
});
try {
String result = f2.join();
System.out.printf("%d. whenComplete: c1=%s, c2=%s, result is %s%n", i, c1, c2, result);
} catch (CompletionException e) {
Throwable t = e.getCause();
System.out.printf("%d. whenComplete: c1=%s, c2=%s, exception is %s%n", i, c1, c2, t.getClass().getSimpleName());
}
}
static void handle(int i, boolean c1, boolean c2) {
new WhenCompleteSurvey(c1, c2).handle(i);
}
static void whenComplete(int i, boolean c1, boolean c2) {
new WhenCompleteSurvey(c1, c2).whenComplete(i);
}
public static void main(String... args) throws InterruptedException {
handle(1, false, false);
handle(2, false, true);
handle(3, true, false);
handle(4, true, true);
System.out.println();
whenComplete(5, false, false);
whenComplete(6, false, true);
whenComplete(7, true, false);
whenComplete(8, true, true);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment