Skip to content

Instantly share code, notes, and snippets.

@aruis
Created September 11, 2018 08:40
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 aruis/135f6e1fa678fc5024ea20db4b9b4eee to your computer and use it in GitHub Desktop.
Save aruis/135f6e1fa678fc5024ea20db4b9b4eee to your computer and use it in GitHub Desktop.
CompletableFuture demo
package com.aruistar.studyjavaten;
import org.junit.Test;
import java.util.Arrays;
import java.util.List;
import java.util.Random;
import java.util.concurrent.*;
import java.util.stream.Collectors;
import static org.junit.Assert.*;
/**
* https://www.ibm.com/developerworks/cn/java/j-cf-of-jdk8/index.html
*/
public class CompletableFutureTest {
@Test
public void completedFutureExample() {
CompletableFuture<String> cf = CompletableFuture.completedFuture("message");
assertTrue(cf.isDone());
assertEquals("message", cf.getNow(null));
}
@Test
public void runAsyncExample() throws InterruptedException {
CompletableFuture<Void> cf = CompletableFuture.runAsync(() -> {
assertTrue(Thread.currentThread().isDaemon());
randomSleep();
});
assertFalse(cf.isDone());
Thread.sleep(2000);
assertTrue(cf.isDone());
}
@Test
public void thenApplyExample() {
CompletableFuture<String> cf = CompletableFuture.completedFuture("message").thenApply(s -> {
assertFalse(Thread.currentThread().isDaemon());
return s.toUpperCase();
});
assertEquals("MESSAGE", cf.getNow(null));
}
@Test
public void thenApplyAsyncExample() {
CompletableFuture<String> cf = CompletableFuture.completedFuture("message").thenApplyAsync(s -> {
assertTrue(Thread.currentThread().isDaemon());
randomSleep();
return s.toUpperCase();
});
assertNull(cf.getNow(null));
assertEquals("MESSAGE", cf.join());
}
static ExecutorService executor = Executors.newFixedThreadPool(3, new ThreadFactory() {
int count = 1;
@Override
public Thread newThread(Runnable runnable) {
return new Thread(runnable, "custom-executor-" + count++);
}
});
@Test
public void thenApplyAsyncWithExecutorExample() {
CompletableFuture<String> cf = CompletableFuture.completedFuture("message").thenApplyAsync(s -> {
assertTrue(Thread.currentThread().getName().startsWith("custom-executor-"));
assertFalse(Thread.currentThread().isDaemon());
randomSleep();
return s.toUpperCase();
}, executor);
assertNull(cf.getNow(null));
assertEquals("MESSAGE", cf.join());
}
@Test
public void thenAcceptExample() {
StringBuilder result = new StringBuilder();
CompletableFuture.completedFuture("thenAccept message")
.thenAccept(s -> result.append(s));
assertEquals(result.toString(), "thenAccept message");
assertTrue("Result was empty", result.length() > 0);
}
@Test
public void thenAcceptAsyncExample() {
StringBuilder result = new StringBuilder();
CompletableFuture<Void> cf = CompletableFuture.completedFuture("thenAcceptAsync message")
.thenAcceptAsync(s -> result.append(s));
cf.join();
assertTrue("Result was empty", result.length() > 0);
}
@Test
public void completeExceptionallyExample() {
CompletableFuture<String> cf = CompletableFuture
.completedFuture("message")
.thenApplyAsync(String::toUpperCase, CompletableFuture.delayedExecutor(1, TimeUnit.SECONDS));
CompletableFuture<String> exceptionHandler = cf.handle((s, th) -> (th != null) ? "message upon cancel" : "");
cf.completeExceptionally(new RuntimeException("completed exceptionally"));
assertTrue("Was not completed exceptionally", cf.isCompletedExceptionally());
try {
cf.join();
fail("Should have thrown an exception");
} catch (CompletionException ex) { // just for testing
assertEquals("completed exceptionally", ex.getCause().getMessage());
}
assertEquals("message upon cancel", exceptionHandler.join());
}
@Test
public void cancelExample() {
CompletableFuture cf = CompletableFuture.completedFuture("message").thenApplyAsync(String::toUpperCase,
CompletableFuture.delayedExecutor(1, TimeUnit.SECONDS));
CompletableFuture cf2 = cf.exceptionally(throwable -> "canceled message");
assertTrue("Was not canceled", cf.cancel(true));
assertTrue("Was not completed exceptionally", cf.isCompletedExceptionally());
assertEquals("canceled message", cf2.join());
}
@Test
public void applyToEitherExample() {
String original = "Message";
CompletableFuture<String> cf1 = CompletableFuture.completedFuture(original)
.thenApplyAsync(this::delayedUpperCase);
CompletableFuture<String> cf2 = cf1.applyToEither(
CompletableFuture.completedFuture(original).thenApplyAsync(this::delayedLowerCase),
s -> s + " from applyToEither");
assertEquals(cf2.join(), "MESSAGE from applyToEither");
}
@Test
public void acceptEitherExample() {
String original = "Message";
StringBuilder result = new StringBuilder();
CompletableFuture cf = CompletableFuture.completedFuture(original)
.thenApplyAsync(this::delayedUpperCase)
.acceptEither(CompletableFuture.completedFuture(original).thenApplyAsync(this::delayedLowerCase),
s -> result.append(s).append("acceptEither"));
cf.join();
assertTrue("Result was empty", result.toString().endsWith("acceptEither"));
}
@Test
public void runAfterBothExample() {
String original = "Message";
StringBuilder result = new StringBuilder();
CompletableFuture.completedFuture(original).thenApply(String::toUpperCase).runAfterBoth(
CompletableFuture.completedFuture(original).thenApply(String::toLowerCase),
() -> result.append("done"));
assertEquals(result.toString(), "messagedone");
assertTrue("Result was empty", result.length() > 0);
}
@Test
public void thenAcceptBothExample() {
String original = "Message";
StringBuilder result = new StringBuilder();
CompletableFuture.completedFuture(original).thenApply(String::toUpperCase).thenAcceptBoth(
CompletableFuture.completedFuture(original).thenApply(String::toLowerCase),
(s1, s2) -> result.append(s1 + s2));
assertEquals("MESSAGEmessage", result.toString());
}
@Test
public void thenCombineExample() {
String original = "Message";
CompletableFuture cf = CompletableFuture.completedFuture(original).thenApply(this::delayedUpperCase)
.thenCombine(CompletableFuture.completedFuture(original).thenApply(this::delayedLowerCase),
(s1, s2) -> s1 + s2);
assertEquals("MESSAGEmessage", cf.getNow(null));
}
@Test
public void thenCombineAsyncExample() {
String original = "Message";
CompletableFuture cf = CompletableFuture.completedFuture(original)
.thenApplyAsync(this::delayedUpperCase)
.thenCombine(CompletableFuture.completedFuture(original).thenApplyAsync(this::delayedLowerCase),
(s1, s2) -> s1 + s2);
assertEquals("MESSAGEmessage", cf.join());
}
@Test
public void thenComposeExample() {
String original = "Message";
CompletableFuture cf = CompletableFuture.completedFuture(original).thenApply(this::delayedUpperCase)
.thenCompose(upper -> CompletableFuture.completedFuture(original).thenApply(this::delayedLowerCase)
.thenApply(s -> upper + s));
assertEquals("MESSAGEmessage", cf.join());
}
@Test
public void anyOfExample() {
StringBuilder result = new StringBuilder();
List<String> messages = Arrays.asList("a", "b", "c");
List<CompletableFuture> futures = messages.stream()
.map(msg -> CompletableFuture.completedFuture(msg).thenApply(this::delayedUpperCase))
.collect(Collectors.toList());
CompletableFuture.anyOf(futures.toArray(new CompletableFuture[futures.size()])).whenComplete((res, th) -> {
if (th == null) {
assertTrue(isUpperCase((String) res));
result.append(res);
}
});
assertTrue("Result was empty", result.length() > 0);
}
@Test
public void allOfExample() {
StringBuilder result = new StringBuilder();
List<String> messages = Arrays.asList("a", "b", "c");
List<CompletableFuture> futures = messages.stream()
.map(msg -> CompletableFuture.completedFuture(msg).thenApply(s -> delayedUpperCase(s)))
.collect(Collectors.toList());
CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()])).whenComplete((v, th) -> {
futures.forEach(cf -> assertTrue(isUpperCase((String) cf.getNow(null))));
result.append("done");
});
System.out.println(result);
assertTrue("Result was empty", result.length() > 0);
}
@Test
public void allOfAsyncExample() {
StringBuilder result = new StringBuilder();
List<String> messages = Arrays.asList("a", "b", "c");
List<CompletableFuture> futures = messages.stream()
.map(msg -> CompletableFuture.completedFuture(msg).thenApplyAsync(this::delayedUpperCase))
.collect(Collectors.toList());
CompletableFuture allOf = CompletableFuture.allOf(futures.toArray(new CompletableFuture[futures.size()]))
.whenComplete((v, th) -> {
futures.forEach(cf -> assertTrue(isUpperCase((String) cf.getNow(null))));
result.append("done");
});
allOf.join();
assertTrue("Result was empty", result.length() > 0);
}
boolean isUpperCase(String s) {
return s.toUpperCase().equals(s);
}
String delayedUpperCase(String s) {
randomSleep();
return s.toUpperCase();
}
String delayedLowerCase(String s) {
randomSleep();
return s.toLowerCase();
}
void randomSleep() {
try {
Thread.sleep(new Random().nextInt(2000));
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
@truongmanhsang
Copy link

thanks.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment