zoukankan      html  css  js  c++  java
  • Java中的CompletableFuture超时使用

    我喜欢Java 8的CompletableFuture,但它有它的缺点: 惯用的超时处理就是其中之一。

    JAVA 8我们只能收集异常信息,再次执行什么的(以下是JAVA8解决超时的方式,获取结果后你该做什么做什么):

    //我们让list里传入方法的参数1号报错和5号超时
    public class Test4 {
    
        private static final ScheduledExecutorService scheduler =
                Executors.newScheduledThreadPool(
                        1,
                        r -> {
                            Thread thread = new Thread(r);
                            thread.setName("failAfter-%d");
                            thread.setDaemon(true);
                            return thread;
                        });
    
        public static void main(String[] args) throws InterruptedException, ExecutionException {
            System.out.println("-------开始------");
            final CompletableFuture<Object> oneSecondTimeout = failAfter(Duration.ofSeconds(2))
                    .exceptionally(xxx -> "超时");
            List<Object> collect = Stream.of("1", "2", "3", "4", "5", "6", "7")
                    .map(x -> CompletableFuture.anyOf(createTaskSupplier(x)
                            , oneSecondTimeout))
                    .collect(Collectors.toList())
                    .stream()
                    .map(CompletableFuture::join)
                    .collect(Collectors.toList());
            System.out.println("-------结束------");
            System.out.println(collect.toString());
        }
    
        public static CompletableFuture<String> createTaskSupplier(String x) {
            return CompletableFuture.supplyAsync(getStringSupplier(x))
                    .exceptionally(xx -> xx.getMessage());
        }
    
    
        public static Supplier<String> getStringSupplier(String text) {
            return () -> {
                System.out.println("开始 " + text);
                if ("1".equals(text)) {
                    throw new RuntimeException("运行时错误");
                }
                try {
                    if ("5".equals(text))
                        setSleepTime(20);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("停止 " + text);
                return text+"";
            };
        }
    
        static void  setSleepTime(int SleepTime) throws InterruptedException {
            TimeUnit.SECONDS.sleep(SleepTime);
        }
    
        public static <T> CompletableFuture<T> failAfter(Duration duration) {
            final CompletableFuture<T> promise = new CompletableFuture<>();
            scheduler.schedule(() -> {
                final TimeoutException ex = new TimeoutException("Timeout after " + duration);
                return promise.completeExceptionally(ex);
            }, duration.toMillis(), TimeUnit.MILLISECONDS);
            return promise;
        }
    
    }
    
    
    
    //执行结果:
    -------开始------
    开始 1
    开始 2
    停止 2
    开始 3
    停止 3
    开始 4
    停止 4
    开始 5
    开始 6
    停止 6
    开始 7
    停止 7
    -------结束------
    [java.lang.RuntimeException: 运行时错误, 2号, 3号, 4号, 超时, 6号, 7号]

     

    幸运的是,JDK 9带来了两种新方法,可以为每个人提供渴望的功能 - 这对于确保在使用异步处理时的正确弹性至关重要。

     

    在这篇超短篇文章中,尝试帮助大家对这个新API方法的认识。

     

    CompletableFuture#orTimeout

    简单地说,在调用上述方法之后,如果未在指定的超时内完成,将来会抛出ExecutionException。

     

    一个简单的例子:

    CompletableFuture<Integer> future = CompletableFuture.supplyAsync(this::computeEndlessly)
      .orTimeout(1, TimeUnit.SECONDS);
    
    future.get(); // java.util.concurrent.ExecutionException after waiting for 1 second
    

    由于设置了timeout为1秒,那么在get那里等待1秒后抛错

    CompletableFuture#completeOnTimeout

    在这种情况下,我们可以在达到超时后返回默认值:

    CompletableFuture<Integer> future = CompletableFuture.supplyAsync(this::computeEndlessly)
      .completeOnTimeout(42, 1, TimeUnit.SECONDS);
    
    Integer result = future.get(); // 42
    

    超时1秒后不是报错,而是返回了预设的42这个值,前提条件是你必须预设默认值。

     

    就这么简单,虽然我不一定喜欢我们总是被迫预先计算默认值的事实。

  • 相关阅读:
    面试问题
    知识点整合
    前端错误
    基于.NET平台常用的框架整理
    BFC和haslayout
    javascript面向对象
    javascript变量的作用域
    2014-05-26 总结
    2014-05-23 总结
    PHP实现mvc模式的思想
  • 原文地址:https://www.cnblogs.com/47Gamer/p/13684070.html
Copyright © 2011-2022 走看看