首页 > 编程语言 >【Java】CompletableFutureTimeoutUtils

【Java】CompletableFutureTimeoutUtils

时间:2023-03-16 13:12:47浏览次数:32  
标签:Java return future CompletableFuture new CompletableFutureTimeoutUtils static fi

CompletableFuture Timeout for JDK 8

import lombok.NonNull;

import java.util.ArrayDeque;
import java.util.Deque;
import java.util.concurrent.*;
import java.util.function.BiConsumer;
import java.util.function.Supplier;

import static java.util.Objects.isNull;

public class CompletableFutureTimeoutUtils {

    /**
     * 单例延时调度程序,仅用于启动和取消任务
     */
    static final class Delayer {
        static final class DaemonThreadFactory implements ThreadFactory {
            @Override
            public Thread newThread(@NonNull Runnable r) {
                Thread t = new Thread(r);
                t.setDaemon(true);
                t.setName("CompletableFutureDelayScheduler");
                return t;
            }
        }

        static final ScheduledThreadPoolExecutor delayer;

        // 注意,这里使用一个线程就可以搞定 因为这个线程并不真的执行请求 仅仅只是用于启动和取消任务
        static {
            (delayer = new ScheduledThreadPoolExecutor(
                    1, new Delayer.DaemonThreadFactory())).
                    setRemoveOnCancelPolicy(true);
        }

        static ScheduledFuture<?> delay(Runnable command, long delay, TimeUnit unit) {
            return delayer.schedule(command, delay, unit);
        }
    }

    /**
     * 超时时以抛异常的形式结束任务
     */
    static final class Timeout implements Runnable {
        final CompletableFuture<?> f;

        Timeout(CompletableFuture<?> f) {
            this.f = f;
        }

        @Override
        public void run() {
            if (f != null && !f.isDone()) {
                f.completeExceptionally(new TimeoutException());
            }
        }
    }

    /**
     * 在超时时完成
     */
    static final class DelayedCompleter<U> implements Runnable {
        final CompletableFuture<U> f;
        final U u;

        DelayedCompleter(CompletableFuture<U> f, U u) {
            this.f = f;
            this.u = u;
        }

        @Override
        public void run() {
            if (f != null) {
                f.complete(u);
            }
        }
    }

    /**
     * 取消不需要的超时任务
     */
    static final class Canceller implements BiConsumer<Object, Throwable> {
        final Future<?> f;

        Canceller(Future<?> f) {
            this.f = f;
        }

        @Override
        public void accept(Object ignore, Throwable ex) {
            if (ex == null && f != null && !f.isDone()) {
                f.cancel(false);
            }
        }
    }

    @SuppressWarnings("unchecked")
    static <R, T extends Throwable> R typeErasure(final Throwable throwable) throws T {
        throw (T) throwable;
    }

    static <T> T timeoutDefault(Throwable throwable, T value) {
        final Deque<Throwable> queue = new ArrayDeque<>();
        while (throwable != null && !queue.contains(throwable)) {
            queue.push(throwable);
            throwable = throwable.getCause();
        }
        final Throwable cause = queue.peek();
        if (cause instanceof TimeoutException) {
            return value;
        }
        return CompletableFutureTimeoutUtils.<T, RuntimeException>typeErasure(cause);
    }

    static <T> CompletableFuture<T> timeoutAfter(long timeout, @NonNull TimeUnit unit) {
        CompletableFuture<T> result = new CompletableFuture<>();
        Delayer.delay(() -> result.completeExceptionally(new TimeoutException()), timeout, unit);
        return result;
    }

    public static <T> CompletableFuture<T> completeOnTimeout(@NonNull CompletableFuture<T> future, T value, long timeout, @NonNull TimeUnit unit) {
        // migrate from jdk9
        if (isNull(future.getNow(null))) {
            future.whenComplete(new Canceller(Delayer.delay(new DelayedCompleter<>(future, value), timeout, unit)));
        }
        return future;

        // another implementation
//        return future.applyToEither(timeoutAfter(timeout, unit), Function.identity())
//                .exceptionally(ex -> timeoutDefault(ex, value));
    }

    public static <T> CompletableFuture<T> orTimeout(@NonNull CompletableFuture<T> future, long timeout, @NonNull TimeUnit unit) {
        // migrate from jdk9
        if (isNull(future.getNow(null))) {
            future.whenComplete(new Canceller(Delayer.delay(new Timeout(future), timeout, unit)));
        }
        return future;

        // another implementation
//        return future.applyToEither(timeoutAfter(timeout, unit), Function.identity());
    }


    public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "正常";
        });
//        CompletableFuture<String> within = completeOnTimeout(future, "超时", 3, TimeUnit.SECONDS);
        CompletableFuture<String> within = orTimeout(future, 1, TimeUnit.SECONDS);
        log.info(within.get());
    }

}

标签:Java,return,future,CompletableFuture,new,CompletableFutureTimeoutUtils,static,fi
From: https://www.cnblogs.com/zhuzhongxing/p/17222168.html

相关文章

  • Java for循环介绍
    基本语法语法格式:for(①初始化部分;②循环条件部分;④迭代部分){         ③循环体部分;}执行过程:①-②-③-④-②-③-④-②-③-④-.....-②图示:说明:......
  • JavaScript随笔
    数据类型简单数据类型(原始类型):Undefined、Null、Boolean、Number、String和Symbol复杂数据类型:Object深拷贝与浅拷贝浅拷贝Object.assignArray.prototype.slice()......
  • java实现一组数据计算同比环比(终极版)
    本篇基于下面两篇博客的内容整合实现:java实现一组数据计算同比环比CGLIB基于一个已有类动态生成一个子类bean(转)之前的博客中已经捋清了在只有日期和一列数据的情况下动......
  • JavaIO中直接内存的使用
    注:本文转自:https://www.toutiao.com/article/7198357822390977080/?log_from=ed0bb42919105_1678896533085本次分享主要由io与nio读取文件速度差异的情况,去了解nio为什么......
  • day94-javaweb-servlet路径问题
    servlet路径问题在web.xml中设置不同映射走的对应的路径<!--可以自定义后缀实现请求路径注意:*前面不能加项目映射的路径hello/sasasas.ggugu......
  • JavaBean
    实体类JavaBean有特定的写法:●必须要有一个无参构造●属性必须私有化●必须有对应的get/set方法一般用来和数据库的字段做映射:ORMORM:对象关系映射●表-->类●字段-->......
  • day93- javaweb-servlet学习
    javaweb的Servlet1.下载maven,tomcat试了10版本的tomcat,好像不兼容,果断放弃安装了tomcat9,就成功了,真是神奇,高了我半天查了各种攻略,tomcat10确实是bug一堆2.从maven中导......
  • java.lang.ClassNotFoundException: com.mysql.jdbc.Driver
    在一个servlet中连接数据库,加载驱动报错,将异常抛了出来。  解决方案:创建的Maven项目中,在web.xml中引入了mysql的驱动,但是创建的servlet需要使用Tomcat服务器,Tomcat中......
  • java_int数组转byte数组的一种方法
    Java:int数组转byte数组的一种方法记录一种int数组转byte数组的方法,无意中看到的。之前都是通过移位操作完成的,现在发现通过系统API就能实现:packagecom.yongdami.test......
  • Java 使用 ResourceBundle 类读取 properties 文件中文乱码的解决方案
    Java使用ResourceBundle类读取properties文件中文乱码的解决方案https://www.cnblogs.com/poterliu/p/10159577.htmlJava使用java.util.ResourceBundle类的方式来......