package org.webpieces.util.futures; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutionException; import org.junit.Assert; import org.junit.Test; public class TestFutures { //private static final Logger log = LoggerFactory.getLogger(TestFutures.class); @Test public void testRegisterTwoListenersToSameFuture() { CompletableFuture<Integer> future = new CompletableFuture<Integer>(); future.thenAccept(f -> fire(f)); future.thenAccept(f -> fire2(f)); future.thenAccept(f -> fire(f+2)); future.thenAccept(f -> fire(f+3)); future.complete(5); } private Object fire2(Integer f) { System.out.println("fire2="+f); return null; } private Object fire(Integer f) { System.out.println("f="+f); return null; } public void testBlowTheStack() throws InterruptedException { recurse(0); System.out.println("done"); Thread.sleep(5000); } private void recurse(int counter) { CompletableFuture<Integer> future = writeData(counter); future.thenAccept(p -> recurse(p+1)).join(); } private CompletableFuture<Integer> writeData(int counter) { System.out.println("counter="+counter); if(counter == 1455) { System.out.println("mark"); } CompletableFuture<Integer> future = new CompletableFuture<Integer>(); future.complete(counter); return future; } @Test public void testCompletableFuture() throws InterruptedException { System.out.println("thread="+Thread.currentThread()); CompletableFuture<Integer> myFuture = new CompletableFuture<>(); myFuture.thenAccept(intResult -> log(intResult)); CompletableFuture<String> result = myFuture.thenApply(p -> translate(p)); result.handle((r, e) -> handle(r, e)); result.cancel(true); myFuture.complete(8); } private String handle(String r, Throwable e) { if(r != null) { System.out.println("result"); } else { System.out.println("FINISHED fail. thread="+Thread.currentThread()); e.printStackTrace(); } return "done"; } private void log(Integer intResult) { System.out.println("int result="+intResult+" thread="+Thread.currentThread()); } private String translate(Integer p) { System.out.println("(translate)thread="+Thread.currentThread()); return p+"str"; } /** * Some times you want code to run success or fail and to propagate so here is how * @throws ExecutionException * @throws InterruptedException */ @Test public void testAFinallyMethodWithCompletableFutures() throws InterruptedException, ExecutionException { CompletableFuture<Integer> myFuture = new CompletableFuture<>(); CompletableFuture<Integer> newFuture = myFuture.thenApply(intResult -> throwException()); myFuture.complete(5); Assert.assertFalse(myFuture.isCompletedExceptionally()); Assert.assertTrue(newFuture.isCompletedExceptionally()); CompletableFuture<Integer> future2 = newFuture.handle((r, e) -> { if(r != null) return r; else if(e != null) throw new RuntimeException(e); else throw new RuntimeException("weird"); }); Assert.assertTrue(future2.isCompletedExceptionally()); CompletableFuture<Object> future = newFuture.handle((r, e) -> { if(r != null) return r; else if(e != null) return e; else return new RuntimeException("Asdf"); }); Assert.assertTrue(future.get() instanceof RuntimeException); Assert.assertFalse(future.isCompletedExceptionally()); } public Integer throwException() { throw new RuntimeException("hit here"); } // @Test // public void testExecutor() throws InterruptedException { // CompletableFuture<Integer> future = new CompletableFuture<Integer>(); // // future.complete(6); // // ExecutorService executor = Executors.newFixedThreadPool(5, new NamedThreadFactory("hithere")); // future.thenApplyAsync(v -> logIt(v), executor); // // Thread.sleep(5000); // } // // public int logIt(int v) { // log.info("thread="+Thread.currentThread()+" val="+v); // return v; // } }