异步编程利器:CompletableFuture深度解析

本文已收录至Github,推荐阅读 👉 Java随想录

微信公众号:Java随想录

文章目录

    • 摘要
    • 如何使用
    • 源码解析
      • 基本结构
      • 内部原理
      • 执行流程
    • 方法介绍
      • 创建对象
      • 异步执行任务
      • 链式操作
      • 异步任务组合
      • 异常处理
      • 取值与状态
      • 超时控制与取消操作
      • 依赖
      • 完成
      • 并发限制
      • 记忆窍门
    • 总结

摘要

在异步编程中,我们经常需要处理各种异步任务和操作。Java 8引入的 CompletableFuture 类为我们提供了一种强大而灵活的方式来处理异步编程需求。CompletableFuture 类提供了丰富的方法和功能,能够简化异步任务的处理和组合。

本文将深入解析 CompletableFuture,希望对各位读者能有所帮助。

CompletableFuture 适用于以下场景

  • 并发执行多个异步任务,等待它们全部完成或获取其中任意一个的结果。
  • 对已有的异步任务进行进一步的转换、组合和操作。
  • 异步任务之间存在依赖关系,需要按照一定的顺序进行串行执行。
  • 需要对异步任务的结果进行异常处理、超时控制或取消操作。

如何使用

下面是一个演示 CompletableFuture 如何使用的代码示例:

public class CompletableFutureExample {

    public static void main(String[] args) {
        // 创建CompletableFuture对象,并定义异步任务
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            // 异步任务的逻辑代码
            // 在这里执行耗时操作或其他需要异步执行的任务
            try {
                TimeUnit.SECONDS.sleep(2); // 模拟耗时操作
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "Hello, ";
        });

        // 添加任务完成后的回调方法
        CompletableFuture<String> resultFuture = future.thenApplyAsync(result -> {
            // 任务完成后的处理逻辑
            // result为上一步任务的结果
            return result + "World!";
        });

        // 组合多个CompletableFuture对象
        CompletableFuture<String> combinedFuture = future.thenCombine(resultFuture, (result1, result2) -> {
            // 对多个CompletableFuture的结果进行组合处理
            return result1 + result2 + " Welcome to the CompletableFuture world!";
        });

        // 异常处理
        CompletableFuture<String> exceptionHandledFuture = combinedFuture.exceptionally(ex -> {
            // 异常处理逻辑
            System.out.println("任务执行出现异常:" + ex.getMessage());
            return "Fallback Result";
        });

        // 等待并获取任务的结果
        try {
            String result = exceptionHandledFuture.get();
            System.out.println("任务的最终结果为:" + result);
        } catch (InterruptedException | ExecutionException e) {
            // 处理异常情况
            e.printStackTrace();
        }
    }
}

结果输出:

任务的最终结果为:Hello, Hello, World! Welcome to the CompletableFuture world!

首先,我们创建了一个CompletableFuture对象future。在future中,我们使用supplyAsync方法定义了一个异步任务,其中 lambda表达式 中的代码会在另一个线程中执行。在这个例子中,我们模拟了一个耗时操作,通过TimeUnit.SECONDS.sleep(2)暂停了2秒钟。

然后,我们添加了一个回调方法resultFuture。在这个回调方法中,将前一个异步任务的结果作为参数进行处理,并返回处理后的新结果。在这个例子中,我们将前一个任务的结果与字符串 “World!” 连接起来,形成新的结果。

接下来,我们使用thenCombine方法组合了两个CompletableFuture对象:futureresultFuture。在这个组合任务中,我们将两个任务的结果进行组合处理,返回最终的结果。在这个例子中,我们将前两个任务的结果与字符串 " Welcome to the CompletableFuture world!" 连接起来。

此外,我们还处理了异常情况。通过exceptionally方法,我们定义了一个异常处理回调方法。如果在任务执行过程中发生了异常,我们可以在这里对异常进行处理,并返回一个默认值作为结果。

最后,我们使用get方法等待并获取最终的任务结果。需要注意的是,get方法可能会阻塞当前线程,直到任务完成并返回结果。在这个例子中,我们使用try-catch块捕获可能的异常情况,并打印出最终的任务结果。

这个例子只是部分展示了CompletableFuture的功能,实际上它比你想象的还要强大!

源码解析

CompletableFuture 的源码非常庞大和复杂,涉及到并发、线程池、同步机制等多方面的知识。在这里,我们只重点介绍 CompletableFuture 的核心实现原理。

基本结构

CompletableFuture 的作者是大名鼎鼎的 Doug Lea。CompletableFuture 类是实现了 Future 和 CompletionStage 接口的一个关键类。它可以表示异步计算的结果,并提供了一系列方法来操作和处理这些结果。

CompletableFuture 内部使用了一个属性result来保存计算结果,以及若干个属性waiters来保存等待结果的任务。当计算完成后,CompletableFuture将会通知所有等待结果的任务,并将结果传递给它们。

为了实现链式操作,CompletableFuture还定义了内部类:Completion, UniCompletion, 和 BiCompletion

Completion, UniCompletion, 和 BiCompletionCompletableFuture 内部用于处理异步任务完成的辅助类。

  • Completion 是一个通用的辅助类,它包含了任务完成后的回调方法,以及处理异常的方法。
  • UniCompletionCompletion 的子类,是一元依赖的基类,用于处理单个任务的完成情况,并提供了更多的方法来处理结果和异常。
  • BiCompletionUniCompletion 的子类,是二元依赖的基类,同时也是多元依赖的基类,用于处理两个任务的完成情况,并提供了更多的方法来组合和处理这两个任务的结果和异常。

这些辅助类在 CompletableFuture 的内部被使用,以实现异步任务的执行、结果的处理和组合等操作。它们提供了一种灵活的方式来处理异步任务的完成情况,并通过回调方法或其他一些方法来处理任务的结果和异常。

内部原理

CompletableFuture中包含两个字段:resultstack。result 用于存储当前CF的结果,stack (Completion)表示当前CF完成后需要触发的依赖动作(Dependency Actions),去触发依赖它的CF的计算,依赖动作可以有多个(表示有多个依赖它的CF),以栈(Treiber stack)的形式存储,stack表示栈顶元素。

CompletableFuture 在设计思想上类似 “观察者模式,每个 CompletableFuture 都可以被看作一个被观察者,其内部有一个Completion类型的链表成员变量stack,用来存储注册到其中的所有观察者。当被观察者执行完成后会弹栈stack属性,依次通知注册到其中的观察者。

执行流程

CompletableFuture 的执行流程如下:

  1. 创建CompletableFuture对象:通过调用CompletableFuture类的构造方法或静态工厂方法创建一个新的CompletableFuture对象。
  2. 定义异步任务:使用supplyAsync()runAsync()等方法定义需要在后台线程中执行的异步任务,这些方法接受一个 lambda表达式 或 Supplier/Runnable 接口作为参数。
  3. 启动异步任务:一旦CompletableFuture对象创建并定义了异步任务,任务会立即在后台线程中开始执行,并返回一个代表异步计算结果的CompletableFuture对象。
  4. 异步任务执行过程:
    • 当异步任务完成时,它会设置自己的结果值,将状态标记为已完成。
    • 如果有其他线程在此之前调用了complete()completeExceptionally()cancel()等方法,可能会影响任务的最终状态。
  5. 注册回调方法:
    • 使用thenApply(), thenAccept(), thenRun()等方法来注册回调函数,当异步任务完成或异常时,这些回调函数会被触发。
    • 回调函数也可以是异步的,通过thenApplyAsync(), thenAcceptAsync(), thenRunAsync()等方法注册。
  6. 组合多个CompletableFuture:
    • 使用thenCompose(), thenCombine(), allOf(), anyOf()等方法,可以将多个CompletableFuture对象进行组合,形成更复杂的异步任务处理流程。
  7. 处理异常:
    • 通过使用exceptionally(), handle(), whenComplete()等方法,可以注册异常处理函数,当异步任务出现异常时,这些处理函数会被触发。
  8. 等待结果:
    • 使用get()join()方法来阻塞当前线程,并等待CompletableFuture对象的完成并获取最终的结果。
    • get()方法会抛出可能的异常(InterruptedException, ExecutionException)。
    • join()方法与get()类似,但不会抛出 checked 异常。
  9. 取消任务:通过调用CompletableFuture对象的cancel()方法取消异步任务的执行。

请注意,以上步骤的顺序和具体实现可能略有不同,但大致上反映了CompletableFuture的执行流程。在实际应用中,我们可以根据需求选择适合的方法来处理异步任务的完成情况、结果、异常以及任务之间的关系。

方法介绍

CompletableFuture类提供了一系列用于处理和组合异步任务的方法。以下是这些方法的介绍:

创建对象

创建一个 CompletableFuture 对象有以下几种方法:

  • 使用 CompletableFuture 的构造方法
CompletableFuture<String> future = new CompletableFuture<>();
  • 使用 CompletableFuture 的静态工厂方法
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    // 异步任务逻辑
    return "Result";
});

CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
    // 异步任务逻辑
});
  • 使用转换方法
CompletableFuture<Integer> transformedFuture = originalFuture.thenApply(result -> {
    // 转换逻辑
    return result.length();
});

originalFuture.thenAccept(result -> {
    // 处理结果逻辑
    System.out.println("Result: " + result);
});

CompletableFuture<Void> runnableFuture = originalFuture.thenRun(() -> {
    // 在结果完成后执行的操作
});
  • 直接创建一个已完成状态的CompletableFuture
//CompletableFuture.completedFuture()直接创建一个已完成状态的CompletableFuture
CompletableFuture<String> cf2 = CompletableFuture.completedFuture("result");

//先初始化一个未完成的CompletableFuture,然后通过complete()、completeExceptionally(),也完成该CompletableFuture
CompletableFuture<String> cf = new CompletableFuture<>();
cf.complete("success");
  • toCompletableFuture
CompletionStage<Integer> stage = CompletableFuture.supplyAsync(() -> 42);

CompletableFuture<Integer> future = stage.toCompletableFuture();

用于将当前的 CompletionStage 对象转换为一个 CompletableFuture 对象。

异步执行任务

以下是在 CompletableFuture 对象上异步执行任务的一些方法示例:

  • supplyAsync(Supplier<U> supplier):异步执行一个有返回值的供应商(Supplier)任务。
CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
    // 异步任务逻辑
    return "Result";
});
  • runAsync(Runnable runnable):异步执行一个没有返回值的任务。
CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
    // 异步任务逻辑
});

链式操作

CompletableFuture提供了不同的方式来对异步任务进行链式操作。

  • thenRun
CompletableFuture<Void> executedFuture = future.thenRun(() -> executeTask());

thenRun方法用于在CompletableFuture完成后执行一个Runnable任务。它返回一个新的CompletableFuture对象,该对象没有返回值。

  • thenAccept
CompletableFuture<Void> acceptedFuture = future.thenAccept(result -> processResult(result));

thenAccept方法用于在CompletableFuture完成后对结果进行处理。它接收一个Consumer函数作为参数,并返回一个新的CompletableFuture对象。

  • thenApply
CompletableFuture<U> appliedFuture = future.thenApply(result -> transformResult(result));

thenApply方法用于在CompletableFuture完成后对结果进行转换。它接收一个Function函数作为参数,并返回一个新的CompletableFuture对象。

  • thenCompose
CompletableFuture<U> composedFuture = future.thenCompose(result -> executeAnotherTask(result));

用于对异步任务的结果进行处理,并返回一个新的异步任务。

  • whenComplete
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 42);

CompletableFuture<Void> whenCompleteFuture = future.whenComplete((result, exception) -> {
    if (exception != null) {
        System.out.println("Exception occurred: " + exception.getMessage());
    } else {
        System.out.println("Result: " + result);
    }
});

whenCompleteFuture.join();

用于在异步任务完成后执行指定的动作。它允许你在任务完成时处理结果或处理异常。

  • thenCompose() 用于对异步任务的结果进行处理,并返回一个新的异步任务。它接受一个函数式接口参数,根据原始任务的结果创建并返回一个新的 CompletionStage 对象。
  • whenComplete() 用于在异步任务完成后执行指定的动作。它接受一个消费者函数式接口参数,用于处理任务的结果或异常,但没有返回值。

异步任务组合

CompletableFuture还提供了一系列方法来组合和处理多个异步任务的结果。

  • allOf
CompletableFuture<Void> allFuture = CompletableFuture.allOf(future1, future2, future3);

allOf方法接收一组CompletableFuture对象作为参数,并返回一个新的CompletableFuture对象,该对象在所有给定的CompletableFuture都完成时完成。这样我们可以等待所有任务都完成后再进行下一步操作。

  • anyOf
CompletableFuture<Object> anyFuture = CompletableFuture.anyOf(future1, future2, future3);

anyOf方法与allOf类似,不同之处在于它返回的CompletableFuture对象在任何一个给定的CompletableFuture完成时就完成。这样我们可以获取最先完成的任务的结果。

  • thenCombine
CompletableFuture<U> combinedFuture = future1.thenCombine(future2, (result1, result2) -> combineResults(result1, result2));

thenCombine方法接收两个CompletableFuture对象和一个函数作为参数,用于指定当这两个CompletableFuture都完成时如何处理它们的结果。返回的新的CompletableFuture对象将接收到计算后的结果。

  • applyToEither
CompletableFuture<U> resultFuture = future1.applyToEither(future2, result -> processResult(result));

applyToEither方法用于获取两个CompletableFuture中任意一个完成的结果,并对该结果进行处理。它接收一个Function函数作为参数,并返回一个新的CompletableFuture对象。

  • acceptEither
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);

future1.acceptEither(future2, result -> {
    System.out.println("Result: " + result);
});

用于在两个 CompletableFuture 对象中任意一个完成时执行指定的操作。该方法接收两个参数:另一个 CompletableFuture 对象和一个消费者函数(Consumer)。当其中任何一个 CompletableFuture 完成时,将其结果作为参数传递给消费者函数进行处理。

  • runAfterBoth
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 42);
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Hello");

CompletableFuture<Void> combinedFuture = future1.runAfterBoth(future2, () -> {
    System.out.println("Both futures completed");
});

combinedFuture.join();

用于在两个异步任务都完成后执行指定的动作,需要注意的是,runAfterBoth() 方法是一个非阻塞方法,动作将在两个异步任务都完成后立即执行。

  • runAfterEither
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> {
    try {
        Thread.sleep(500);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return 42;
});

CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> {
    try {
        Thread.sleep(1000);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    return "Hello";
});

CompletableFuture<Void> eitherFuture = future1.runAfterEither(future2, () -> {
    System.out.println("One of the futures completed");
});

eitherFuture.join();

用于在两个异步任务中任意一个完成后执行指定的动作。

  • thenAcceptBoth
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 42);
CompletableFuture<String> future2 = CompletableFuture.supplyAsync(() -> "Hello");

CompletableFuture<Void> thenAcceptBothFuture = future1.thenAcceptBoth(future2, (result1, result2) -> {
    System.out.println("Action executed with thenAcceptBoth(): " + result1 + ", " + result2);
});

thenAcceptBothFuture.join();

用于在两个异步任务都完成后执行指定的动作。它的作用是接收两个异步任务的结果,并将结果作为参数传递给指定的消费者函数。

异常处理

CompletableFuture提供了多种方式来处理异步任务的异常情况。

  • exceptionally
CompletableFuture<U> exceptionHandledFuture = future.exceptionally(ex -> handleException(ex));

通过exceptionally方法,我们可以对CompletableFuture的异常情况进行处理。它接收一个Function函数作为参数,用于处理异常并返回一个新的CompletableFuture对象。

  • handle
CompletableFuture<U> handledFuture = future.handle((result, ex) -> handleResult(result, ex));

handle方法可以同时处理正常结果和异常情况。它接收一个BiFunction函数作为参数,用于处理结果和异常,并返回一个新的CompletableFuture对象。

  • completeExceptionally
future.completeExceptionally();

异常地完成 CompletableFuture,将结果设置为一个异常。

  • isCompletedExceptionally
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
    throw new RuntimeException("Something went wrong");
});

boolean completedExceptionally = future.isCompletedExceptionally();
System.out.println("Is completed exceptionally: " + completedExceptionally);

该方法返回一个布尔值,表示当前异步任务是否已经异常完成。

  • obtrudeException
CompletableFuture<Integer> future = new CompletableFuture<>();

future.obtrudeException(new RuntimeException("Something went wrong"));

boolean completedExceptionally = future.isCompletedExceptionally();
System.out.println("Is completed exceptionally: " + completedExceptionally);

用于强制将指定的异常作为异步任务的结果,调用 obtrudeException(Throwable ex) 方法后,异步任务将立即完成,并将指定的异常作为结果返回。

取值与状态

  • join
future.join()

join() 方法不会抛出已检查异常,因为它是基于 CompletableFuture 类设计的,如果异步任务抛出异常,join() 方法会将该异常包装在 CompletionException 中并抛出。

  • get
future.get()

get() 方法会抛出一个 InterruptedException 异常和一个 ExecutionException 异常,前者表示获取结果时被中断,后者表示获取结果时任务本身抛出了异常。

future.get(1,TimeUnit.Hours)

有异常则抛出异常,最长等待一个小时,一个小时之后,如果还没有数据,则异常。

  • getNow
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
    // 异步任务逻辑
    return 42;
});

int result = future.getNow(0); // 获取异步操作的结果,如果尚未完成,则返回默认值0

System.out.println("Result: " + result);

getNow(T value)CompletableFuture 类的一个方法,用于获取异步操作的结果,如果异步操作尚未完成,则返回给定的默认值,该方法会立即返回结果,不会阻塞当前线程。

超时控制与取消操作

CompletableFuture也支持超时控制和取消操作,以便更好地管理异步任务的执行。

  • completeOnTimeout
CompletableFuture<U> timeoutFuture = future.completeOnTimeout(defaultResult, timeout, timeUnit);

completeOnTimeout方法在指定的超时时间内等待CompletableFuture的完成,如果超时则将其设置为默认结果。它返回一个新的CompletableFuture对象。

  • cancel
boolean isCancelled = future.cancel(true);

cancel方法可用于取消CompletableFuture的执行。它接收一个boolean参数,指示是否中断正在执行的任务。返回值表示是否成功取消了任务。

  • isCancelled
CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {
    // 异步任务逻辑
    return 42;
});

future.cancel(true); // 取消异步任务

boolean isCancelled = future.isCancelled();
System.out.println("Is cancelled: " + isCancelled);

isCancelled()CompletableFuture 类的一个方法,用于判断当前异步任务是否已被取消。如果异步任务已被取消,则返回 true;否则返回 false

依赖

  • getNumberOfDependents
CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 10);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 20);

CompletableFuture<Integer> combinedFuture = future1.thenCombine(future2, (result1, result2) -> result1 + result2);

int numberOfDependents = combinedFuture.getNumberOfDependents();
System.out.println("Number of dependents: " + numberOfDependents);

getNumberOfDependents() 用于获取当前 CompletableFuture 对象所依赖的其他异步任务的数量。如果没有任何依赖任务,或者所有依赖任务已经完成,则返回的数量为0。

完成

  • complete
future.complete("米饭");

complete(T value):该方法返回布尔值,表示是否成功地将结果设置到 CompletableFuture 中。如果 CompletableFuture 未完成,则将结果设置,并返回 true;如果 CompletableFuture 已经完成,则不进行任何操作并返回 false

  • obtrudeValue
CompletableFuture<Integer> future = new CompletableFuture<>();

future.obtrudeValue(42);

boolean completedNormally = future.isDone() && !future.isCompletedExceptionally();
System.out.println("Is completed normally: " + completedNormally);

用于强制将指定的值作为异步任务的结果,调用 obtrudeValue(T value) 方法后,异步任务将立即完成,并将指定的值作为结果返回。

complete() 不同,obtrudeValue() 必须在任务已经完成的情况下调用,否则会引发 IllegalStateException 异常。并且complete() 方法对于已经完成的任务会忽略额外的完成操作,并返回 false。而obtrudeValue() 方法即使任务已经完成,仍然会强制使用新的结果值,并返回 true

  • isDone
CompletableFuture<Integer> future = CompletableFuture.completedFuture(42);

boolean done = future.isDone();
System.out.println("Is done: " + done);

用于判断当前异步任务是否已经完成(无论是正常完成还是异常完成)。

并发限制

CompletableFuture也支持并发限制,以控制同时执行的异步任务数量。

Executor executor = Executors.newFixedThreadPool(10);
CompletableFuture<U> future = CompletableFuture.supplyAsync(() -> doSomething(), executor);

我们可以通过使用线程池来限制CompletableFuture的并发执行数量。通过创建一个固定大小的线程池,并将其作为参数传递给CompletableFuture,就可以控制并发执行任务的数量。

记忆窍门

CompletableFuture类提供了许多方法,但实际上常用的方法只有几个。为了方便记忆,以下是一些总结的规律:

  • 方法名带Async的都是异步方法,对应的没有Async则是同步方法,比如 thenAcceptthenAcceptAsync
  • 方法名带run的入参为Runnable,且无返回值。
  • 方法名带supply的入参为Supplier,且有返回值。
  • 方法名带Accept的入参为Consumer,且无返回值。
  • 方法名带Apply的入参为Function,且有返回值。
  • 方法名带Either的方法表示谁先完成就消费谁。
  • 方法名带Both的方法表示两个任务都完成才消费。

掌握以上规律后,就可以基本记住大部分方法,剩下的其他方法可以单独记忆。

总结

本文详细探讨了 CompletableFuture 的原理和方法,学习了如何在任务完成后执行操作、处理结果和转换结果。

CompletableFuture是Java中强大的异步编程工具之一,合理利用它的方法和策略可以更好地处理异步任务和操作。

希望本文对读者有所启发和帮助。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/310319.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

yum来安装php727

yum 安装php727,一键安装&#xff0c;都是安装在系统的默认位置&#xff0c;方便快捷 先确定linux平台中centos的版本信息&#xff0c;一下内容针对el7 查看linux版本 &#xff1a; cat /etc/redhat-release 查看内核版本命令&#xff1a; cat /proc/version (0)如果有安装好…

频率阈图像滤波

介绍 频率阈图像滤波是一种在频域中进行图像处理的方法&#xff0c;它基于图像的频率分布来实现滤波效果。具体步骤如下&#xff1a; 将原始图像转换到频域&#xff1a;使用快速傅里叶变换&#xff08;FFT&#xff09;将图像从空间域转换到频域。对频域图像应用频率阈滤波器&a…

力扣 | 139. 单词拆分

主要是要注意组合的顺序是任意的&#xff01;所以就要先选择目标字串&#xff0c;再选择wordDict public boolean wordBreak(String s, List<String> wordDict) {// dp[i]: 表示前 i 个字符组成的子串是否可以被 wordDict 中的字符串组合而成boolean[] dp new boolean[s…

Prometheus实战篇:Prometheus告警简介

Prometheus告警简介 简介 告警能力在Prometheus的架构中被划分为俩个独立的部分.如下图所示,通过在Prometheus中定义AlertRule(告警规则),Prometheus会周期性的对告警规则进行计算,如果满足告警触发条件就会向Alertmanager发送告警信息 alertManager作为一个独立的组件,负责接…

Jenkins-Pipeline语法总结大全

这里写目录标题 pipeline的组成1、pipeline最简单结构1.1、pipeline1.2、stages1.3、stage1.4、steps1.5、agent 2、post3、pipeline支持的命令3.1、environment3.2、tools3.3、input3.4、options3.5、parameters3.6、parallel3.7、triggers3.8、when pipeline的组成 1、pipel…

GPT-4与DALL·E 3:跨界融合,开启绘画与文本的新纪元

在人工智能的发展浪潮中&#xff0c;MidTool&#xff08;https://www.aimidtool.com/&#xff09;的GPT-4与DALLE 3的集成代表了一个跨越式的进步。这一集成不仅仅是技术的结合&#xff0c;更是艺术与文字的完美融合&#xff0c;它为创意产业带来了革命性的变革。本文将探讨GPT…

12.22 探探 数分 已HR面

岗位信息 1222 3.30PM 1面 40min 能感觉数据基建还不是很完善 因此 问了一些指标体系的问题还挺多 自我介绍能力考察1.说说你是怎么异常归因的以付费场景项目为例2.归因中如果遇到一个页面同时存在有3个实验在跑 无法归因出数据的异常是哪个改动造成的怎么办&#xff1f;3.讲…

抖捧AI实景自动直播,开启2024直播新篇章!

在如今互联网的时代&#xff0c;各个行业的实体商家都面临着新的挑战与机遇&#xff0c;而传统做线下经营的方式&#xff0c;已经逐渐被直播与短视频宣传所超越&#xff0c;但还有不少商家思维存在于传统的宣传方式上&#xff0c;也错失了很多的机会&#xff0c;今天就给大家介…

基于JavaWeb+BS架构+SpringBoot+Vue基于web的多媒体素材管理系统的设计和实现

基于JavaWebBS架构SpringBootVue基于web的多媒体素材管理系统的设计和实现 文末获取源码Lun文目录前言主要技术系统设计功能截图订阅经典源码专栏Java项目精品实战案例《500套》 源码获取 文末获取源码 Lun文目录 1 绪 论 1 1.1选题背景与意义 1 1.1 研究背景 1 1.2 研究意义…

操作系统--虚拟内存--物理内存

虚拟内存地址: 出现的原因&#xff1a;单片机时代&#xff0c;cpu直接操作物理内存&#xff0c;每次只能有一个进程操作&#xff0c;如果多个 在 4GB 物理内存的机器上&#xff0c;申请 8G 内存会怎么样&#xff1f; 1、明确是32位机器&#xff0c;还是64位机器 32位&#xf…

api网关-kong

选型 api网关相关功能 服务的路由 动态路由负载均衡 服务发现 限流 熔断、降级 流量管理 黑白名单反爬策略 控制台&#xff1a;通过清晰的UI界面对网关集群进行各项配置。 集群管理&#xff1a;Goku网关节点是无状态的&#xff0c;配置信息自动同步&#xff0c;支持节点水…

照片动起来-yanderifier

&#x1f3e1; 个人主页&#xff1a;IT贫道-CSDN博客 &#x1f6a9; 私聊博主&#xff1a;私聊博主加WX好友&#xff0c;获取更多资料哦~ &#x1f514; 博主个人B栈地址&#xff1a;豹哥教你学编程的个人空间-豹哥教你学编程个人主页-哔哩哔哩视频 目录 图片动起来实现步骤 …

典型的无人机打击技术

无人机打击技术主要指的是用于中和、摧毁或干扰无人机&#xff08;UAV&#xff09;的各种技术手段。 这些技术随着无人机的广泛使用而迅速发展&#xff0c;特别是在军事和安全领域。下面是一些主要的无人机打击技术及其原理&#xff1a; 射频干扰&#xff08;RF Jamming&#x…

开源C语言库Melon之日志模块

本文向大家介绍一个名为Melon的开源C语言库的日志模块。 简述Melon Melon是一个包含了开发中常用的各类组件的开源C语言库&#xff0c;支持Linux、MacOS、Windows系统&#xff0c;可用于服务器开发亦可用于嵌入式开发&#xff0c;无第三方软件依赖&#xff0c;安装简单&…

2023年人工智能的最新发展(下)

目录 1.MidJourney&#xff1a; 2.GAN: 3.Diffusion Model 4.DALLE、Disco Diffusion 5.Stable Diffusion 1.MidJourney&#xff1a; 2023年3月&#xff0c;一组中国小情侣的照片在网络上迅速走红。这组照片看起来普通&#xff0c;就像一对小情侣的合影&#xff0c;但实…

【Hudi数据湖】hudi集成hive同步元数据

摘要 Spark/Flink可以使用Hive的metastore&#xff0c;但是Hive无法通过Hive metastore中的Spark/Flink表直接查询数据。为了解决这个问题&#xff0c;可以配置使用Hive sync。在Spark/Flink操作表的时候&#xff0c;自动同步Hive的元数据。这样就可以通过Hive查询Hudi表的内容…

leetcode动态规划问题总结 Python

目录 一、基础理论 二、例题 1. 青蛙跳台阶 2. 解密数字 3. 最长不含重复字符的子字符串 4. 连续子数组的最大和 5. 最长递增子序列 6. 最长回文字符串 7. 机器人路径条数 8. 礼物的最大价值 一、基础理论 动态规划其实是一种空间换时间的基于历史数据的递推算法&…

8.2、5GMEC认识篇

MEC&#xff1a;多接入边缘计算&#xff08;Multi-access Edge Computing&#xff09;&#xff0c;强调的是边缘侧的计算服务。 MEC最大的好处是就近访问业务&#xff1a;MEC是一个资源池&#xff0c;可以部署各种服务器&#xff0c;把需要就近访问的业务部署在MEC的服务器上&a…

400G-哪个形式因素?(QSFP-DD, OSFP, CFP8)

400G收发器形式因素的发展趋势: 随着新技术的出现&#xff0c;采用新的形式因素和特点并不是什么新鲜事。400G时代即将到来&#xff0c;就像之前的技术周期一样&#xff0c;400G市场将针对特定的网络应用提供不同的收发器形式的因素。 下一代收发器外形因子有三个共同属性&am…

快速排序-排序算法

算法思想 快速排序采用的仍然是分治的思想。 Step1.每次在无序的序列中选取一个基准数。 Step2.然后将大于和小于基准数的元素分别放置于基准数两边。&#xff08;前面部分的元素均小于或等于基准数&#xff0c;后面部分均大于或等于基准数&#xff09; Step3.然后采用分治法&…