【Java】CompletableFutureTimeoutUtils

该代码示例展示了如何使用JavaCompletableFuture进行超时控制。通过创建一个单例的延迟调度程序,实现定时启动和取消任务。当任务超时时,会抛出TimeoutException或完成给定的默认值。此外,还提供了在超时时取消任务的功能。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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);
    }

    public 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());
    }

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值