042 异步编排

文章目录

  • 什么是异步
  • Future
  • 异步编排
    • 1串行关系执行
      • thenRun
      • thenApply
      • thenAccept
      • thenCompose
    • 2聚合AND
      • thenCombine
      • thenAcceptBoth
      • runAfterBoth
    • 3OR聚合
      • applyToEiter
      • acceptEither
      • runAfterEither
    • 4异常处理
      • exceptionally
      • whenComplete
      • handle
  • 异步开启
    • 1RunAsync:没有使用自定义线程池,默认使用的线程池ForkJoinPool.commonPool
    • 2RunAsync使用自己的线程池
    • 3supplyAsync: 有返回值的,关注返回值

什么是异步

异步调用实现一个不需要被等待的方法的返回值;让调用者继续执行(异步执行);在java中,简单的讲就是开启另一个线程完成程序计算,使得调用者继续执行,不需要等待计算的结果,但是调用者仍然需要获取线程的计算结果(不需要同步阻塞等待)。
在这里插入图片描述

Future

Future也是一个异步计算结果返回接口,目的获取返回值结果。但是future在获取返回值结果的时候,方法必须同步阻塞等待返回值结果。

Get:获取结果(等待,阻塞)

Get(timeout):获取结果,指定等待时间

Cancel: 取消当前任务

isDone:判断任务是否已经完成(轮询)

future对于结果获取不是很方便,只能通过同步阻塞的方式获取结果,或者是轮询的方式获取到结果;阻塞的方式获取返回值结果与异步思想相违背,轮询方式又很占用cpu资源,也不能及时得到我们结果。

异步编排

CompletableFuture 可以帮助我们简化异步编程复杂性,提供了函数式编程的能力,可以通过回调函数的方式处理计算结果。

public class CompletableFuture<T> implements Future<T>,CompletionStage<T>

CompletableFuture具有Future的特性,还实现了CompletionStage接口,具备CompletionStage接口的特性:串行执行,并行执行,聚合(AND聚合,OR聚合)

1串行关系执行

串行关系执行: then- 然后,也就是表示下一步,所以通常是一个串行的关系体现,then后面的单词(比如run/apply/accept)就是函数式接口中抽象方法名称;

串行关系执行:利用上一步的执行结果,去进行下一步任务执行,任务执行具有先后顺序,因此把这种操作叫做串行关系。

thenRun

public CompletionStage<Void> thenRun(Runnable action);public CompletionStage<Void> thenRunAsync(Runnable action);public CompletionStage<Void> thenRunAsync(Runnable action,Executor executor);
package com.xd.cubemall.juc;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.*;/*** 并发编程中异步编排*/
@Slf4j
public class AsyncFutureDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {log.info("主线程start...................");//1.public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);// thenRun 没有返回值,也不关心上一步执行结果,只和上一步执行具有顺序关系//2.public CompletionStage<Void> thenRun(Runnable action);CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {log.info("子线程future线程start...................");int i = 10 / 2;log.info("线程名称:{},线程执行结果:{}", Thread.currentThread().getName(), i);log.info("子线程future线程end...................");return i;}).thenRun(() -> {log.info("thenRun子线程开始运行...................");});// 调用执行future.get();log.info("主线程end...................");}}

thenApply

thenApply此方法具有返回值,上一步直接的结果当成传参传递给thenApply,T就是参数类型,U就是返回值类型

public <U> CompletionStage<U> thenApply(Function<? super T,? extends U> fn);public <U> CompletionStage<U> thenApplyAsync(Function<? super T,? extends U> fn);public <U> CompletionStage<U> thenApplyAsync(Function<? super T,? extends U> fn,Executor executor);
package com.xd.cubemall.juc;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.*;/*** 并发编程中异步编排*/
@Slf4j
public class AsyncFutureDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {//1.public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);// thenApply 有返回值,返回值类型是U,跟上一步执行结果有关系,上一步执行结果会被当成参数传递给下一步,参数类型为T//2.public <U> CompletionStage<U> thenApply(Function<? super T,? extends U> fn);// 多线程异步编排CompletableFuture<Long> thenApply = CompletableFuture.supplyAsync(() -> {log.info("子线程future线程start...................");int i = 10 / 2;log.info("线程名称:{},线程执行结果:{}", Thread.currentThread().getName(), i);log.info("子线程future线程end...................");return i;}).thenApply((t) -> {log.info("thenApply子线程开始执行,参数是:{}", t);long res = t * 5;log.info("计算结果:{}", res);return res;});// 调用异步方法Long aLong = thenApply.get();log.info("最终计算结果:{}",aLong);}}

thenAccept

thenAccept:没有返回值,跟上一步执行结果有关系,上一步执行结果将会被下一步消费,参数类型T

public CompletionStage<Void> thenAccept(Consumer<? super T> action);public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action);public CompletionStage<Void> thenAcceptAsync(Consumer<? super T> action,Executor executor);
package com.xd.cubemall.juc;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.*;/*** 并发编程中异步编排*/
@Slf4j
public class AsyncFutureDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {//1.public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);//thenAccept:没有返回值,跟上一步执行结果有关系,上一步执行结果将会被下一步消费,参数类型T//2.public CompletionStage<Void> thenAccept(Consumer<? super T> action);log.info("主线程start...................");CompletableFuture<Void> future = CompletableFuture.supplyAsync(() -> {log.info("子线程future线程start...................");int i = 10 / 2;log.info("线程名称:{},线程执行结果:{}", Thread.currentThread().getName(), i);log.info("子线程future线程end...................");return i;}).thenAccept((t) -> {log.info("thenAccept子线程开始执行,参数是:{}", t);long res = t * 5;log.info("计算结果:{}", res);});// 调用异步方法future.get();log.info("主线程end...................");}}

thenCompose

  1. 有返回值,返回值类型U
  2. 依赖于上一步的返回值结果,上一步返回值结果将会作为参数被传递
  3. 允许对2个CompletionStage流水线进行操作,第一个操作完成时,将第一个操作结果传递第二个CompletionStage
public <U> CompletionStage<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn);public <U> CompletionStage<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn);public <U> CompletionStage<U> thenComposeAsync(Function<? super T,? extends CompletionStage<U>> fn,Executor executor);
package com.xd.cubemall.juc;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.*;
import java.util.function.Function;/*** 并发编程中异步编排*/
@Slf4j
public class AsyncFutureDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {//1.public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);//thenCompose://1) 有返回值,返回值类型U//2) 依赖于上一步的返回值结果,上一步返回值结果将会作为参数被传递//3) 允许对2个CompletionStage流水线进行操作,第一个操作完成时,将第一个操作结果传递第二个CompletionStage//2.public <U> CompletionStage<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn);CompletableFuture<Long> thenCompose = CompletableFuture.supplyAsync(() -> {log.info("子线程future线程start...................");int i = 10 / 2;log.info("线程名称:{},线程执行结果:{}", Thread.currentThread().getName(), i);log.info("子线程future线程end...................");return i;}).thenCompose(new Function<Integer, CompletionStage<Long>>() {@Overridepublic CompletionStage<Long> apply(Integer t) {// 第二次执行CompletableFuture<Long> future = CompletableFuture.supplyAsync(() -> {log.info("thenCompose子线程开始执行,参数是:{}", t);long res = t * 5;log.info("计算结果:{}", res);return res;});return future;}});//调用异步方法Long aLong = thenCompose.get();log.info("最终计算结果: {}",aLong);}}

2聚合AND

Combine…with… 和 both… and … 都是要求两者都必须满足,也就是and且的关系。

thenCombine

thenCombine:
1) 有返回值
2) thenCombine会把两个CompletionStage的任务都执行完毕后,把两个任务的结果一块交给thenCombine去处理

public <U,V> CompletionStage<V> thenCombine(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn);public <U,V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn);public <U,V> CompletionStage<V> thenCombineAsync(CompletionStage<? extends U> other,BiFunction<? super T,? super U,? extends V> fn,Executor executor);
package com.xd.cubemall.juc;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.*;
import java.util.function.Function;/*** 并发编程中异步编排*/
@Slf4j
public class AsyncFutureDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {//1.public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);//thenCombine://1) 有返回值//2) thenCombine会把两个CompletionStage的任务都执行完毕后,把两个任务的结果一块交给thenCombine去处理//2.public <U,V> CompletionStage<V> thenCombine(CompletionStage<? extends U> other, BiFunction<? super T,? super U,? extends V> fn);log.info("主线程start...................");//第一个:CompletionStageCompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> {log.info("子线程future线程start...................");int i = 10 / 4;log.info("线程名称:{},线程执行结果:{}", Thread.currentThread().getName(), i);log.info("子线程future线程end...................");return i;});//第二个:CompletionStageCompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> {log.info("子线程future线程start...................");int i = 10 / 3;log.info("线程名称:{},线程执行结果:{}", Thread.currentThread().getName(), i);log.info("子线程future线程end...................");return i;});// 利用thenCombine方法对f1,f2进行合并操作CompletableFuture<Integer> thenCombine = f1.thenCombine(f2, (t, u) -> {log.info("第一个 CompletableFuture 执行结果{}", t);log.info("第二个 CompletableFuture 执行结果{}", u);return t + u;});//调用异步方法Integer integer = thenCombine.get();log.info("最终异步的调用结果:{}",integer);log.info("主线程end...................");}}

thenAcceptBoth

当2个阶段的CompletionStage都执行完毕后,把结果一块交给thenAcceptBoth进行执行,没有返回值

public <U> CompletionStage<Void> thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T,? super U> action);public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action);public <U> CompletionStage<Void> thenAcceptBothAsync(CompletionStage<? extends U> other,BiConsumer<? super T, ? super U> action,Executor executor);
package com.xd.cubemall.juc;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.*;
import java.util.function.Function;/*** 并发编程中异步编排*/
@Slf4j
public class AsyncFutureDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {//1.public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);//thenAcceptBoth: 当2个阶段的CompletionStage都执行完毕后,把结果一块交给thenAcceptBoth进行执行,没有返回值//2.public <U> CompletionStage<Void> thenAcceptBoth(CompletionStage<? extends U> other,BiConsumer<? super T,? super U> action);log.info("主线程start...................");//第一个:CompletionStageCompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> {log.info("子线程future线程start...................");int i = 10 / 4;log.info("线程名称:{},线程执行结果:{}", Thread.currentThread().getName(), i);log.info("子线程future线程end...................");return i;});//第二个:CompletionStageCompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> {log.info("子线程future线程start...................");int i = 10 / 3;log.info("线程名称:{},线程执行结果:{}", Thread.currentThread().getName(), i);log.info("子线程future线程end...................");return i;});// 利用thenAcceptBoth方法对f1,f2进行合并操作CompletableFuture<Void> f = f1.thenAcceptBoth(f2, (t, u) -> {log.info("第一个 CompletableFuture 执行结果{}", t);log.info("第二个 CompletableFuture 执行结果{}", u);});//调用异步方法f.get();log.info("主线程end...................");}}

runAfterBoth

无返回值,当2个阶段的CompletionStage都执行完毕后,才会执行下一步操作

public CompletionStage<Void> runAfterBoth(CompletionStage<?> other,Runnable action);public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action);public CompletionStage<Void> runAfterBothAsync(CompletionStage<?> other,Runnable action,Executor executor);
package com.xd.cubemall.juc;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.*;
import java.util.function.Function;/*** 并发编程中异步编排*/
@Slf4j
public class AsyncFutureDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {//1.public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);//runAfterBoth: 无返回值,当2个阶段的CompletionStage都执行完毕后,才会执行下一步操作//2.public CompletionStage<Void> runAfterBoth(CompletionStage<?> other,Runnable action);log.info("主线程start...................");//第一个:CompletionStageCompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> {log.info("子线程future线程start...................");int i = 10 / 4;log.info("线程名称:{},线程执行结果:{}", Thread.currentThread().getName(), i);log.info("子线程future线程end...................");return i;});//第二个:CompletionStageCompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> {log.info("子线程future线程start...................");int i = 10 / 3;log.info("线程名称:{},线程执行结果:{}", Thread.currentThread().getName(), i);log.info("子线程future线程end...................");return i;});// 利用runAfterBoth方法对f1,f2进行合并操作CompletableFuture<Void> f = f1.runAfterBoth(f2, () -> {log.info("有个任务在执行:runAfterBoth方法正在运行......");});f.get();log.info("主线程end...................");}}

3OR聚合

applyToEiter

1.针对于2个阶段CompletionStage,将计算速度最快的那个CompletionStage的结果作为下一步处理的消费;
2.有返回值

public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T,U> fn);public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T,U> fn,Executor executor);public <U> CompletionStage<U> applyToEitherAsync(CompletionStage<? extends T> other,Function<? super T,U> fn);
package com.xd.cubemall.juc;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.*;
import java.util.function.Function;/*** 并发编程中异步编排*/
@Slf4j
public class AsyncFutureDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {//public <U> CompletionStage<U> applyToEither(CompletionStage<? extends T> other,Function<? super T,U> fn);// 1.applyToEither特点:针对于2个阶段CompletionStage,将计算速度最快的那个CompletionStage的结果作为下一步处理的消费;// 2.有返回值log.info("主线程start...................");//第一个:CompletionStageCompletableFuture<Integer> f1 = CompletableFuture.supplyAsync(() -> {log.info("子线程future线程start...................");int i = 10 / 4;log.info("线程名称:{},线程执行结果:{}", Thread.currentThread().getName(), i);log.info("子线程future线程end...................");return i;});//第二个:CompletionStageCompletableFuture<Integer> f2 = CompletableFuture.supplyAsync(() -> {log.info("子线程future线程start...................");int i = 10 / 3;log.info("线程名称:{},线程执行结果:{}", Thread.currentThread().getName(), i);log.info("子线程future线程end...................");return i;});// 利用applyToEither方法对f1,f2进行合并操作,合并操作关系:ORCompletableFuture<Integer> f = f1.applyToEither(f2, result -> {log.info("applyToEither子线程开始执行,参数是:{}", result);return result;});Integer r1 = f.get();log.info("最终计算结果: {}",r1);log.info("主线程end...................");}}

acceptEither

public CompletionStage<Void> acceptEither(CompletionStage<? extends T> other,Consumer<? super T> action);public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action);public CompletionStage<Void> acceptEitherAsync(CompletionStage<? extends T> other,Consumer<? super T> action,Executor executor);

runAfterEither

public CompletionStage<Void> runAfterEither(CompletionStage<?> other,Runnable action);public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action);public CompletionStage<Void> runAfterEitherAsync(CompletionStage<?> other,Runnable action,Executor executor);

4异常处理

exceptionally

public CompletionStage<T> exceptionally(Function<Throwable,? extends T> fn);
package com.xd.cubemall.juc;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.*;
import java.util.function.Function;/*** 并发编程中异步编排*/
@Slf4j
public class AsyncFutureDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {//public CompletionStage<T> exceptionally(Function<Throwable,? extends T> fn);log.info("主线程start...................");//第一个:CompletionStageCompletableFuture<Integer> f = CompletableFuture.supplyAsync(() -> {log.info("子线程future线程start...................");int i = 10 / 0;log.info("线程名称:{},线程执行结果:{}", Thread.currentThread().getName(), i);log.info("子线程future线程end...................");return i;}).exceptionally((t)->{log.info("业务执行失败:{}",t.getMessage());return null;});Integer r1 = f.get();log.info("主线程end...................");}}

whenComplete

public CompletionStage<T> whenComplete(BiConsumer<? super T,? super Throwable> action);public CompletionStage<T> whenCompleteAsync(BiConsumer<? super T, ? super Throwable> action);public CompletionStage<T> whenCompleteAsync(BiConsumer<? super T,? super Throwable> action,Executor executor);
package com.xd.cubemall.juc;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.*;
import java.util.function.Function;/*** 并发编程中异步编排*/
@Slf4j
public class AsyncFutureDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {//public CompletionStage<T> whenComplete(BiConsumer<? super T,? super Throwable> action);log.info("主线程start...................");//第一个:CompletionStageCompletableFuture<Integer> f = CompletableFuture.supplyAsync(() -> {log.info("子线程future线程start...................");int i = 10 / 0;log.info("线程名称:{},线程执行结果:{}", Thread.currentThread().getName(), i);log.info("子线程future线程end...................");return i;}).whenComplete((t, u) -> {log.info("上一步执行结果:{}",t);//判断if(u!=null){log.info("执行错误,有异常:{}",u.getMessage());}});Integer integer = f.get();log.info("最终执行结果:{}",integer);log.info("主线程end...................");}}

handle

try{}finally{}:对上一步执行结果进行处理,还可以处理异常任务

public <U> CompletionStage<U> handle(BiFunction<? super T,Throwable,? extends U> fn);public <U> CompletionStage<U> handleAsync(BiFunction<? super T,Throwable,? extends U> fn);public <U> CompletionStage<U> handleAsync(BiFunction<? super T, Throwable,? extends U> fn, Executor executor);
package com.xd.cubemall.juc;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.*;
import java.util.function.Function;/*** 并发编程中异步编排*/
@Slf4j
public class AsyncFutureDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {//public <U> CompletionStage<U> handle(BiFunction<? super T,Throwable,? extends U> fn);//try{}finally{}:对上一步执行结果进行处理,还可以处理异常任务log.info("主线程start...................");//第一个:CompletionStageCompletableFuture<Integer> f = CompletableFuture.supplyAsync(() -> {log.info("子线程future线程start...................");int i = 10 / 2;log.info("线程名称:{},线程执行结果:{}", Thread.currentThread().getName(), i);log.info("子线程future线程end...................");return i;}).handle((t, u) -> {int res = -1;if (u != null) {log.info("执行错误:{}", u.getMessage());} else {res = t * 5;}return res;});Integer integer = f.get();log.info("最终执行结果:{}",integer);log.info("主线程end...................");}}

异步开启

CompletableFuture提供了4个静态的方法,来创建一个异步操作(异步开启,从这4个静态的方法开始即可)

runAsync:没有返回值的方法,不关注返回值

public static CompletableFuture<Void> runAsync(Runnable runnable);public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor);

supplyAsync:有返回值,关注返回值的。

public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier,Executor executor);

1RunAsync:没有使用自定义线程池,默认使用的线程池ForkJoinPool.commonPool

package com.xd.cubemall.juc;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutionException;/*** 并发编程中异步编排*/
@Slf4j
public class AsyncFutureDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {log.info("主线程start...................");//runAsync: 实现异步编排,没有返回值//public static CompletableFuture<Void> runAsync(Runnable runnable);CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {log.info("子线程future线程start...................");int i = 10/2;log.info("线程名称:{},线程执行结果:{}",Thread.currentThread().getName(),i);log.info("子线程future线程end...................");});// 调用异步任务future.get();log.info("主线程end...................");}
}

2RunAsync使用自己的线程池

package com.xd.cubemall.juc;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.*;/*** 并发编程中异步编排*/
@Slf4j
public class AsyncFutureDemo {public static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(Runtime.getRuntime().availableProcessors(),9,3,TimeUnit.SECONDS,new LinkedBlockingDeque<>(3),Executors.defaultThreadFactory(),new ThreadPoolExecutor.AbortPolicy());public static void main(String[] args) throws ExecutionException, InterruptedException {log.info("主线程start...................");//runAsync: 实现异步编排,没有返回值//public static CompletableFuture<Void> runAsync(Runnable runnable,Executor executor);CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {log.info("子线程future线程start...................");int i = 10/2;log.info("线程名称:{},线程执行结果:{}",Thread.currentThread().getName(),i);log.info("子线程future线程end...................");},threadPool);// 调用异步任务future.get();log.info("主线程end...................");}
}

3supplyAsync: 有返回值的,关注返回值

package com.xd.cubemall.juc;import lombok.extern.slf4j.Slf4j;import java.util.concurrent.*;/*** 并发编程中异步编排*/
@Slf4j
public class AsyncFutureDemo {public static void main(String[] args) throws ExecutionException, InterruptedException {log.info("主线程start...................");//supplyAsync:实现异步编排,有返回值//public static <U> CompletableFuture<U> supplyAsync(Supplier<U> supplier);CompletableFuture<Integer> uCompletableFuture = CompletableFuture.supplyAsync(() -> {log.info("子线程future线程start...................");int i = 10 / 2;log.info("线程名称:{},线程执行结果:{}", Thread.currentThread().getName(), i);log.info("子线程future线程end...................");return i;});// 调用异步编排futureInteger integer = uCompletableFuture.get();log.info("supplyAsync异步编排的返回值结果:{}",integer);log.info("主线程end...................");}}

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

【算法设计与分析】采用特征方程求解递归方程

文章目录 K阶常系数线性齐次递归方程K阶常系数线性【非】齐次递归方程例题例1&#xff1a;齐次无重根例2&#xff1a;齐次有重根例3&#xff1a;非齐次&#xff0c;g(n)是n的多项式例4&#xff1a;非齐次&#xff0c;g(n)是n的指数形式&#xff0c;a不是重根 练习其它求解递归方…

SAP ABAP开发学习——function alv复选框设置

1.关于报表复选框的创建 首先该报表要调用功能函数 这里参照SLIS_LAYOUT_ALV定义字段 参照来源 具体字段的定义 双击 双击这两个查看需要的字段 box_fieldname就是复选框 需要在内表定义需要的名称&#xff0c;这里使用‘BOX 相关内容完成

5.7 与 8.0 对相同文件的 LOAD DATA 语句结果不同

5.7 与 8.0 对相同文件的 LOAD DATA 语句结果不同 问题描述 某客户现场支持&#xff0c;由MySQL 5.7.21升级MySQL 8.0.25后&#xff0c;通过LOAD DATA导入文件&#xff0c;当同一会话连续导入不同的编码&#xff08;UTF8/GB18030&#xff09;文件时会出现乱码。数据库版本未升…

河南梦想城供配电项目-综合监控平台[智能运维+集中监控]

河南梦想城供配电项目-综合监控平台软件 可分为主机系统&#xff08;针对单个站房的实时监测&#xff09;和集中云平台&#xff08;针对多个站房的集中管理&#xff09;&#xff0c;可实现电气设备隐患预警&#xff0c;站房环境风险可控&#xff0c;系统与电力平台以IEC61850标…

每日计划-1114

完成 14. 最长公共前缀 #include <string> #include <vector>class Solution { public:string longestCommonPrefix(std::vector<std::string>& strs) {if (!strs.size()) {return "";}int length strs[0].size();int count strs.size();fo…

《深度学习》AlexNet网络

文章目录 1.AlexNet的网络架构2.示例&#xff1a;手写数字识别2.1 数据读取 学习目标&#xff1a; 知道AlexNet网络结构能够利用AlexNet完成图像分类 2012年&#xff0c;AlexNet横空出世&#xff0c;该模型的名字源于论⽂第⼀作者的姓名AlexKrizhevsky 。AlexNet使⽤了8层卷积…

嵌入式软件开发环境的搭建

1.ARM指令模拟器环境搭建 keil软件 KEIL是公司的名称&#xff0c;有时候也指KEIL公司的所有软件开发工具。2005年&#xff0c;Keil被ARM公司收购&#xff0c;成为 ARM的子公司之一。 MDK&#xff08;Microcontroller Development Kit&#xff09; &#xff0c;也称MDK-ARM、…

模型广场上线!一键开启免费体验

模型广场上新&#xff0c;多款模型任君挑选~ 限时免费体验&#xff01;快来开启你的AI创作之旅吧~ 01 comfyui 工作流 ComfyUI是一个基于Stable Diffusion开发的图形用户界面&#xff08;GUI&#xff09;&#xff0c;它将Stable Diffusion的流程拆分成节点&#xff0c;你能够…

Java的dto,和多表的调用

1理论 需求是新增菜品eg&#xff1a;菜名:豆腐脑&#xff1b;口味&#xff1a;甜口&#xff0c;咸口&#xff0c; 菜单表&#xff1a;dish&#xff1b;口味表dish_flavor&#xff1b; 1dto:数据传输对象 新建一个dishDto对象有两个表里的属性 2用到两个表&#xff0c;dish,d…

python爬虫js逆向进阶——请求的网页源码被加密,解密方法全过程(19)

文章目录 1、任务目标2、网页分析3、代码编写1、任务目标 目标网站:https://jzsc.mohurd.gov.cn/data/company,该网站的网页源码被加密了,用于本文测验 要求:解密该网站的网页源码,请求网站并返回解密后的明文数据,网页内容如下: 2、网页分析 进入网站,打开开发者模式,…

二、vue指令

1、v-bind ⽬标 : 给标签属性设置 vue 变量的值 vue 指令 , 实质上就是特殊的 html 标签属性 , 特点 : v- 开头 每个指令 , 都有独⽴的作⽤ 语法&#xff1a; v-bind:属性名"vue变量" 简写&#xff1a; : 属性名"vue变量" <!-- vue 指令 -v-bi…

VASA-1: Lifelike Audio-Driven Talking Faces Generated in Real Time

TL;DR 2024 年微软发表的数字人工作 VASA-1&#xff0c;支持基于单人头像照片和语音音频输入&#xff0c;来实时生成数字人视频。支持在线生成高达 40 FPS 的 512512 分辨率视频&#xff0c;目前为数不多能做到实时推理且效果很好的 talking face 工作。 Paper name VASA-1:…

【Ubuntu24.04】服务部署(基础)

目录 0 背景1 设置静态IP2 连接服务器3 部署服务3.1 安装JDK3.2 下载并安装MySQL8.43.2.1 从官网下载 APT Repository 配置文件3.2.2 安装 MySQL8.43.2.3 配置远程连接 3.3 下载并配置Redis3.4 上传jar包并部署应用3.5 开放端口 4 总结 0 背景 在成功安装了Ubuntu24.04操作系统…

[Java]Properties类加载配置文件

在我JDBC的文章末尾展示了完整的JDBC使用流程。但那种方式有一个问题&#xff0c;如果项目需要更换数据库&#xff0c;或者这个项目本来就是要使用多种数据库&#xff0c;那么像这种把信息写死在代码里边的编写模式&#xff0c;是肯定不行的。实际开发中肯定不会使用这种把信息…

STM32CUBEIDE的使用【五】TFT_LCD

硬件平台&#xff1a; 正点原子潘多拉开发板 STM32L475 软件平台&#xff1a; STM3232CubeMX 、STM32CUBEIDE 屏幕尺寸为1.3寸 分辨率240*240 16位真彩色 使用SPI接口驱动TFT_LCD 用来显示ASCII 字符图像和彩色功能 CubeMX配置 Source Code 创建app_lcd.c文件 #include &q…

Python数据分析NumPy和pandas(三十二、数据拆分-应用-合并)

最常用的 GroupBy 方法是 apply&#xff0c;apply 将正在操作的对象拆分为多个片段&#xff0c;在每个片段上调用传递给它函数&#xff0c;然后尝试连接这些片段。 还是用前面的小费数据集tips.csv&#xff0c;它的内容如下图&#xff1a; 假设我们想按smoker进行分组并选择前…

【毫米波雷达(九)】前雷达软件开发遇到的问题汇总及解决方法

前雷达软件开发遇到的问题汇总及解决方法 一、CAN/CANFD通信1、雷达CAN未能正常发出数据2、雷达在车上接收不到车身信息3、程序下载失败4、DV试验发送数据偶发断连5、发送感知信息丢帧或者丢报文6、上电发出第一帧的报文时间长7、ZCANPRO有错误帧二、协议转换&#xff08;以太网…

linux 下调试 bmp280 气压传感器

供自己备忘&#xff1b; linux 下有自带的 bmp280 驱动&#xff0c;实际测试数据抖动不理想&#xff1b; 于是自己重写一个 bmp280 驱动&#xff0c;实际测试数据依旧抖动&#xff0c;不理想&#xff1b; 考虑使用 SPL06 来测试看看效果&#xff1b; 1. 参考资料&#xff1…

『VUE』26. props实现子组件传递数据给父组件(详细图文注释)

目录 本节内容示例代码总结 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 欢迎关注 『VUE』 专栏&#xff0c;持续更新中 本节内容 父组件传子组件–props 子组件传父组件–自定义事件 本节讲子组件传父组件–通过props里的方法传递,就是父亲写了一个函数,给子组件调用,然后…

Linux编辑/etc/fstab文件不当,不使用快照;进入救援模式

目录 红帽镜像9救援模式 现象 解决 第一步&#xff1a;修改启动参数以进入救援模式 第二步&#xff1a;进入救援模式、获取root权限、编辑/etc/fstab文件 第三步&#xff1a;编辑好后在重启 下面是ai给的模板 红帽镜像9救援模式 编辑/etc/fstab不当时 17 /dev/nvme0n3p1…