/** * This blocking function attempts to send the message passed in as a parameter. This {@link * AmqpsIotHubConnection} handles all calls to this method. * * <p>Only the first call to this method will result in an attempt to send. Until the message has * been sent, all other calls to this method will block. Once a message has been sent and this * method notified that it has been sent, this method will be invoked again if was previously * another call to send a message. * * <p>If a message has been passed down to the handler for sending but the message isn't sent * after a default constant number of seconds, the {@link AmqpsTransport} will set an ERROR status * code on the message and it will placed back onto the queue. * * @throws IOException If {@link AmqpsIotHubConnectionBaseHandler} has not been initialized. */ protected synchronized void send(Tuple<CompletableFuture<Boolean>, byte[], Object> message) throws IOException { if (this.state == ReactorState.CLOSED) { throw new IllegalStateException( "The AMQPS IotHub Connection is currently closed. Call open() before attempting to send a message."); } if (message != null) { if (this.inProgressMessageMap.size() >= this.maxQueueSize * 0.9) { message.V1.completeExceptionally( new Throwable("Insufficient link credit to send message.")); } else { try { // Use the content and ID fields of the input message to have the handler create and send // the message CompletableFuture<Integer> deliveryFuture = amqpsHandler.createBinaryMessage((byte[]) message.V2, message.V3); // Wait for a period of time before rejecting the message new Thread( () -> { try { Thread.sleep(DEFAULT_DELIVERY_WAIT_TIME_SECONDS * 1000); deliveryFuture.completeExceptionally( new Throwable("Default timeout exceeded before this message was sent.")); } catch (InterruptedException e) { e.printStackTrace(); } }) .start(); // Wait for the deliveryFuture to be completed, providing the delivery hash code. // When this future completes, the message has been SENT Integer deliveryHash = deliveryFuture.get(); inProgressMessageMap.put(deliveryHash, message); } catch (InterruptedException e) { e.printStackTrace(); } // The message was unable to be sent, exceptionally complete that future causing the message // to be put back on the queue. catch (ExecutionException e) { message.V1.completeExceptionally(e.getCause()); this.fail(e.getCause()); } // There was some other problem sending, exceptionally complete that future causing the // message to be put back on the queue. catch (Exception e) { if (message != null) { message.V1.completeExceptionally(e); } this.fail(e); } } } else { throw new IOException("Cannot send an unitialized message."); } }
@Test public void test_findPriceInUSD() { Shop s1 = shops.get(0); String product = "MacBook 11"; Future<Double> priceInUSD = CompletableFuture.supplyAsync(() -> s.getPrice(product)) .thenCombine( CompletableFuture.supplyAsync(() -> ExchangeService.getRate(USD, FRANC)), (price, rate) -> price * rate); }
public Stream<CompletableFuture<String>> findPriceStream(String product) { return shops .stream() .map(shop -> CompletableFuture.supplyAsync(() -> shop.getPrice(product), executor)) .map(future -> future.thenApply(Quote::parse)) .map( future -> future.thenCompose( quote -> CompletableFuture.supplyAsync( () -> Discount.applyDiscount(quote), executor))); }
private <T> void retryHelper( BiFunction<Integer, Integer, CompletableFuture<T>> function, CompletableFuture<T> result) { final int retries = doRetry(function); final int index = getNextIndex(function); final long start = System.currentTimeMillis(); if (index > -1) { try { function .apply(index, retries) .whenComplete( (obj, ex) -> { if (ex == null) { registerSuccess(function, index, start); result.complete(obj); } else { if (retries > 0) { registerFailure(function, index, false); retryHelper(function, result); } else { registerFailure(function, index, true); result.completeExceptionally(ex); } } }); } catch (Exception e) { if (retries > 0) { registerFailure(function, index, false); retryHelper(function, result); } else { registerFailure(function, index, true); result.completeExceptionally(e); } } } else { result.completeExceptionally(new LoadBalancerException("All backends suspended")); } }
private static void asyncInCompletableFuture() { CompletableFuture.supplyAsync( () -> { for (int i = 0; i < 1000; ++i) { if (i % 5 == 0) System.out.println("Doing hard work ...."); } return new File("/tmp/foo"); }) .thenApply(File::toPath) .thenAccept(System.out::println); }
public void printPricesStream() { long start = System.nanoTime(); CompletableFuture[] futures = findPriceStream("myPhone") .map( f -> f.thenAccept( s -> System.out.println( s + " (done in " + ((System.nanoTime() - start) / 1_000_000) + " msecs)"))) .toArray(size -> new CompletableFuture[size]); CompletableFuture.allOf(futures).join(); }
public void stop() { if (stopped) { throw new RuntimeException("Already stopped or in progress"); } stopped = true; CompletableFuture<?>[] futures = cachedDispatchQueues .values() .stream() .filter(v -> v != null) .toArray(CompletableFuture<?>[]::new); CompletableFuture.allOf(futures).join(); service.shutdown(); }
@Override @SuppressWarnings("unchecked") public CompletableFuture<Void> dispatchAsync(String dispatchId, Runnable task) { try { return (CompletableFuture<Void>) cachedDispatchQueues.compute( dispatchId, (k, queue) -> { CompletableFuture<Void> voidCompletableFuture = (queue == null) ? CompletableFuture.runAsync(task) : ((CompletableFuture<Void>) queue).thenRunAsync(task); return voidCompletableFuture; }); } catch (Throwable t) { log.warn( "Exception thrown when calling dispatchAngGetFuture for dispatchId[{}]", dispatchId, t); throw t; } }
@Override public void rejectedExecution(Runnable r, ThreadPoolExecutor executor) { if (r instanceof RunnableScheduledFuture) { Object callable = ReflectionUtil.getFieldValue(r, "callable"); Object cfAsync = ReflectionUtil.getFieldValue(callable, "task"); r = (Runnable) cfAsync; } if (r instanceof ForkJoinTask && r.toString().contains("CompletableFuture$Async")) { Field field = ReflectionUtil.getField(r, "dst"); // jdk8u20 if (field == null) { field = ReflectionUtil.getField(r, "dep"); // jdk8u40 } Object dst = ReflectionUtil.getFieldValue(r, field); if (dst instanceof CompletableFuture) { ((CompletableFuture) dst).cancel(false); log.debug("Canceled completable future {}", r); } } else if (r instanceof Future) { ((Future) r).cancel(false); log.debug("Canceled future {}", r); } }