CompletableFuture使用(全网最详细!!!)

news2024/12/29 11:52:07

一、runAsync

1、runAsync(Runnable)

2、runAsync(Runnable, Executor)

二、supplyAsync

1、supplyAsync(Supplier)

2、supplyAsync(Supplier , Executor)

三、CompletableFuture中 get 与 join的区别

四、thenApply方法

1、thenApply(Function)

五、handle方法

1、handle(BiFunction fn),>

2、handleAsync(BiFunction fn,Executor),>

3、thenCombine

4、thenCombineAsync

六、thenCompose方法

1、thenCompose

七、allOf / anyOf


普通情况下,我们的接口逻辑都是串行化的,有时候在我们方法中可能存在着非常耗时的操作这样就会造成代码阻塞,但是呢,为了用户的体验,我们可能需要将一些复杂的数据开启线程进行异步处理。

所谓异步,其实就是实现一个可无需等待被调用函数的返回值而让操作继续运行的方法,简单的讲就是另启一个线程来完成调用中的部分计算,使调用继续运行或返回,而不需要等待计算结果。

Java8 提供的CompletableFuture 可以自定义线程池或使用默认线程池对数据进行异步处理,且可以根据需求选择是否返回异步结果!灵活的使用CompletableFuture可以让我们感受java8的异步编程之美!

以下,便是CompletableFuture 的异步操作创建方式示例。

CompletableFuture的思想是,当被调用时,它们会立即被安排启动开始执行异步任务(与流式操作中的延迟计算有着明显区别)。

一、runAsync

1、runAsync(Runnable)

使用ForkJoinPool.commonPool()作为它的线程池执行异步代码,

public class AsyncDemo01 {
    public static void main(String[] args) {
        //当前调用者线程为:main
        System.out.println("当前调用者线程为:" + Thread.currentThread().getName());
        CompletableFuture.runAsync(() -> {
            // 异步方法内当前执行线程为:ForkJoinPool.commonPool-worker-1
            System.out.println("异步方法内当前执行线程为:" + Thread.currentThread().getName());
            System.out.println(111);
        });
    }
}
2、runAsync(Runnable, Executor)

使用指定的线程池执行异步代码。此异步方法无法返回值。

public class AsyncDemo02 {
    public static void main(String[] args) {
        //当前调用者线程为:main
        System.out.println("当前调用者线程为:" + Thread.currentThread().getName());
        
        // fixme 根据阿里规约 建议真实开发时使用 ThreadPoolExecutor 定义线程池
        ExecutorService threadPool = Executors.newFixedThreadPool(10);
        
        CompletableFuture.runAsync(() -> {
            // 异步方法内当前执行线程为:pool-1-thread-1
            System.out.println("异步方法内当前执行线程为:" + Thread.currentThread().getName());
            System.out.println(111);
        }, threadPool);
        
        // 演示代码,所以选择执行完后关闭线程池
        threadPool.shutdown();
    }
}

二、supplyAsync

1、supplyAsync(Supplier)

使用ForkJoinPool.commonPool()作为它的线程池执行异步代码,异步操作有返回值

public class SupplyDemo01 {
    public static void main(String[] args) {
        CompletableFuture<String> supplyAsync = CompletableFuture.supplyAsync(() -> {
            // 异步方法内当前执行线程为:ForkJoinPool.commonPool-worker-1
            System.out.println("异步方法内当前执行线程为:" + Thread.currentThread().getName());
            // 模拟返回值
            return "hello,world";
        });
        // 获取异步线程执行结果
        System.out.println(supplyAsync.join());
    }
}
2、supplyAsync(Supplier , Executor)

使用指定线程池 来执行可获取返回值的异步任务

public class SupplyDemo02 {
    public static void main(String[] args)  {
        // fixme 根据阿里规约 建议真实开发时使用 ThreadPoolExecutor 定义线程池
        ExecutorService threadPool = Executors.newFixedThreadPool(10);
        CompletableFuture<String> supplyAsync = CompletableFuture.supplyAsync(() -> {
            // 异步方法内当前执行线程为:pool-1-thread-1
            System.out.println("异步方法内当前执行线程为:" + Thread.currentThread().getName());
            // 模拟耗时与返回结果
            try {
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            return "hello,world";
        },threadPool);
        // 获取异步线程执行结果
        System.out.println(supplyAsync.join());
    }
}

三、CompletableFuture中 get 与 join的区别

CompletableFuture 使用 supplyAsync 来执行异步任务的话,可通过调用 get 或 join方法便可获取异步线程的执行结果。

不同:get方法返回结果,抛出的是检查异常,必须用户throw或者try/catch处理,join返回结果,抛出未检查异常。

相同:join和get方法都是依赖于完成信号并返回结果T的阻塞方法。(阻塞调用者线程,等待异步线程返回结果)。

join: 

get:

 需要注意的是, completableFuture 的get 方法 有重载,还有一个可传入获取结果等待时间的get方法

如果超过等待时间,异步线程还未返回结果,那么get 调用者线程则会抛出TimeoutException 异常

 

四、thenApply方法

当我们第二个任务依赖第一个任务的结果的时候,可以使用 thenApply相关方法来把这两个线程串行化,参数是一个Function(代表着我们需要传入一个转换的函数 具体可参考JAVA8 函数式接口)thenApply 只可以执行正常的任务,任务出现异常则不会执行 thenApply 方法;如果当第一个任务出现异常时仍要执行第二个任务,可以使用下方的Handle方法

public <U> CompletableFuture<U> thenApply(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn)
public <U> CompletableFuture<U> thenApplyAsync(Function<? super T,? extends U> fn, Executor executor)

T:上一个异步任务返回值

U: 当前执行最后返回值

1、thenApply(Function)

thenApplythenApply中的线程为调用者线程,与CompletableFuture 底层默认所用的 ForkJoin无关!

示例:

public class SupplyDemo03 {
    public static void main(String[] args) {
        CompletableFuture<String> future = CompletableFuture
                .supplyAsync(() -> {
                    System.out.println(Thread.currentThread().getName());
                    return "hello";
                }).thenApply(e -> {
                    System.out.println(Thread.currentThread().getName());
                    return e + ",";
                }).thenApply(e -> {
                    System.out.println(Thread.currentThread().getName());
                    return (e + "world").toUpperCase();
                });
        System.out.println(future.join());
    }
}

程序执行情况:

最后JOIN 获取结果为 HELLO,WORLD

三个线程分别是 ForkJoinPool.commonPool-worker-1,main,main(2)thenApplyAsync(Function)
thenApplyAsync当我们第二个任务依赖第一个任务的结果的时候,且第二个任务也想采用异步的方式,则可以使用 thenApplyAsync(Function)

public static void main(String[] args) {
    CompletableFuture<String> future = CompletableFuture
        .supplyAsync(() -> {
            System.out.println(Thread.currentThread().getName());
            return "hello";
        }).thenApplyAsync(e -> {
        System.out.println(Thread.currentThread().getName());
        return e + ",";
    }).thenApplyAsync(e -> {
        System.out.println(Thread.currentThread().getName());
        return (e + "world").toUpperCase();
    });
    System.out.println(future.join());
}

程序执行情况:

最后JOIN 获取结果为 HELLO,WORLD

三个线程均是 是 ForkJoinPool.commonPool-worker-xxxx

当然,我们也可以使用 thenApplyAsync(Function, Executor) 来使用自定义线程池执行我们的异步任务

五、handle方法

handle 是执行任务完成时对结果的处理, handle 方法和 thenApply 方法处理方式大致一样,不同的是 handle 是在任务完成后再执行且Handle可以根据可以根据任务是否有异常来进行做相应的后续处理操作。

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);
1、handle(BiFunction<T, Throwable, U> fn)

使用Handler方法 预估异常情况 进行逻辑处理 默认handle中使用的线程为调用者线程

public class HandleDemo01 {
    public static void main(String[] args) {
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前supplyAsync 执行线程:" + Thread.currentThread().getName());
            // 模拟异常
            int a = 1 / 0;
            return "hello";
        }).handle((x, t) -> {
            System.out.println("当前handle 执行线程:" + Thread.currentThread().getName());
            if (t != null) {
                // 出现异常 打印异常信息 或者doSomething
                System.out.println("发现上一个异步任务出异常了" + t.getMessage());
            } else {
                // 未出异常 doSomething
                return x;
            }
            // 设置默认结果
            return "error";
        });
        System.out.println(future.join());
    }
}

程序执行情况:

当前supplyAsync 执行线程:ForkJoinPool.commonPool-worker-1
当前handle 执行线程:main
发现上一个异步任务出异常了java.lang.ArithmeticException: / by zero
error

2、handleAsync(BiFunction<T, Throwable, U> fn,Executor)

使用自定义的线程 (或者使用默认的ForkJoin)进行异步处理第二个线程的任务

public class HandleDemo01 {
    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newFixedThreadPool(2);
        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前supplyAsync 执行线程:" + Thread.currentThread().getName());
            // 模拟异常
            int a = 1 / 0;
            return "hello";
        },threadPool).handleAsync((x, t) -> {
            System.out.println("当前handle 执行线程:" + Thread.currentThread().getName());
            if (t != null) {
                // 出现异常 打印异常信息 或者doSomething
                System.out.println("发现上一个异步任务出异常了" + t.getMessage());
            } else {
                // 未出异常 doSomething
                return x;
            }
            // 设置默认结果
            return "error";
        },threadPool);
        System.out.println(future.join());
    }
}

程序执行情况:

当前supplyAsync 执行线程:pool-1-thread-1
当前handle 执行线程:pool-1-thread-2
发现上一个异步任务出异常了java.lang.ArithmeticException: / by zero
error

七、thenCombine方法
thenCombine 会在两个CompletableFuture任务都执行完成后,把两个任务的结果一块处理。

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);
3、thenCombine

thenCombine 会在两个CompletableFuture任务都执行完成后,调用者线程会把两个异步任务的结果一块处理

public class ThenCombineDemo01 {
    public static void main(String[] args) {
        CompletableFuture<String> helloAsync = CompletableFuture.supplyAsync(() -> {
            System.out.println("hello 执行线程:" + Thread.currentThread().getName());
            return "hello";
        });
        CompletableFuture<String> worldAsync = CompletableFuture.supplyAsync(() -> {
            System.out.println("world 执行线程:" + Thread.currentThread().getName());
            return "world";
        });
        CompletableFuture<String> result = worldAsync.thenCombine(helloAsync, (hello, world) -> {
            System.out.println("result 执行线程:" + Thread.currentThread().getName());
            return (hello + "," + world).toUpperCase();
        });
        System.out.println("获取结果 执行线程:" + Thread.currentThread().getName());
        System.out.println("两个异步任务合并结果:" + result.join());
    }
}

程序执行结果:

hello 执行线程:ForkJoinPool.commonPool-worker-1
world 执行线程:ForkJoinPool.commonPool-worker-1
result 执行线程:main
获取结果 执行线程:main
两个异步任务合并结果:WORLD,HELLO

4、thenCombineAsync

thenCombineAsync 会在两个CompletableFuture任务都执行完成后,再用一个异步线程把两个任务的结果一块处理

六、thenCompose方法

thenCompose 方法允许你对两个CompletableFuture任务进行流水线操作,当第一个异步任务操作完成时,会将其结果作为参数传递给第二个任务。

public <U> CompletableFuture<U> thenCompose(Function<? super T, ? extends CompletionStage<U>> fn);
public <U> CompletableFuture<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn) ;
public <U> CompletableFuture<U> thenComposeAsync(Function<? super T, ? extends CompletionStage<U>> fn, Executor executor) ;
1、thenCompose

thenCompose当第一个异步任务操作完成时,会将其结果作为参数传递给第二个任务(第二个任务为串行化操作,由调用者线程执行)

public class ThenComposeDemo01 {
    public static void main(String[] args) {
        CompletableFuture<String> result = CompletableFuture.supplyAsync(() -> {
            System.out.println("hello 执行线程:" + Thread.currentThread().getName());
            return "hello";
        }).thenCompose((hello -> {
            System.out.println("thenCompose 执行线程:" + Thread.currentThread().getName());
            return CompletableFuture.supplyAsync((hello + "world")::toUpperCase);
        }));
        System.out.println("获取结果 执行线程:" + Thread.currentThread().getName());
        System.out.println("两个异步任务流水线执行结果:" + result.join());
    }
}

程序执行情况:

hello 执行线程:ForkJoinPool.commonPool-worker-1
thenCompose 执行线程:main
获取结果 执行线程:main
两个异步任务流水线执行结果: HELLOWORLD(2)thenComposeAsync

thenComposeAsync当第一个异步任务操作完成时,会将其结果作为参数传递给第二个任务(第二个任务仍为异步线程执行操作,可由默认ForkJoin线程池执行,也可使用自定义线程池)

public class ThenComposeDemo02 {
    public static void main(String[] args) {
        ExecutorService threadPool = Executors.newFixedThreadPool(2);
        CompletableFuture<String> result = CompletableFuture.supplyAsync(() -> {
            System.out.println("hello 执行线程:" + Thread.currentThread().getName());
            return "hello";
        },threadPool).thenComposeAsync((hello -> {
            System.out.println("thenCompose 执行线程:" + Thread.currentThread().getName());
            return CompletableFuture.supplyAsync((hello + "world")::toUpperCase);
        }),threadPool);
        System.out.println("获取结果 执行线程:" + Thread.currentThread().getName());
        System.out.println("两个异步任务流水线执行结果:" + result.join());
    }
}

程序执行情况:

hello 执行线程:pool-1-thread-1
获取结果 执行线程:main
thenCompose 执行线程:pool-1-thread-2
两个异步任务流水线执行结果: HELLOWORLD

七、allOf / anyOf

allOf:CompletableFuture是多个任务都执行完成后才会执行,只有有一个任务执行异常,则返回的CompletableFuture执行get方法时会抛出异常,如果都是正常执行,则get返回null。

anyOf :CompletableFuture是多个任务只要有一个任务执行完成,则返回的CompletableFuture执行get方法时会抛出异常,如果都是正常执行,则get返回执行完成任务的结果。

测试代码:

public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {
            try {
                System.out.println(Thread.currentThread() + " cf1 do something....");
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("cf1 任务完成");
            return "cf1 任务完成";
        });
 
        CompletableFuture<String> cf2 = CompletableFuture.supplyAsync(() -> {
            try {
                System.out.println(Thread.currentThread() + " cf2 do something....");
                int a = 1/0;
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("cf2 任务完成");
            return "cf2 任务完成";
        });
 
        CompletableFuture<String> cf3 = CompletableFuture.supplyAsync(() -> {
            try {
                System.out.println(Thread.currentThread() + " cf2 do something....");
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("cf3 任务完成");
            return "cf3 任务完成";
        });
 
        CompletableFuture<Void> cfAll = CompletableFuture.allOf(cf1, cf2, cf3);
        System.out.println("cfAll结果->" + cfAll.get());
}
 
 
public static void main(String[] args) throws ExecutionException, InterruptedException {
        CompletableFuture<String> cf1 = CompletableFuture.supplyAsync(() -> {
            try {
                System.out.println(Thread.currentThread() + " cf1 do something....");
                Thread.sleep(2000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("cf1 任务完成");
            return "cf1 任务完成";
        });
 
        CompletableFuture<String> cf2 = CompletableFuture.supplyAsync(() -> {
            try {
                System.out.println(Thread.currentThread() + " cf2 do something....");
                Thread.sleep(5000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("cf2 任务完成");
            return "cf2 任务完成";
        });
 
        CompletableFuture<String> cf3 = CompletableFuture.supplyAsync(() -> {
            try {
                System.out.println(Thread.currentThread() + " cf2 do something....");
                Thread.sleep(3000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("cf3 任务完成");
            return "cf3 任务完成";
        });
 
        CompletableFuture<Object> cfAll = CompletableFuture.anyOf(cf1, cf2, cf3);
        System.out.println("cfAll结果->" + cfAll.get());
}

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

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

相关文章

运行ChatGLM大模型时,遇到的各种报错信息及解决方法

①IMPORTANT: You are using gradio version 3.49.0, however version 4.29.0 is available, please upgrade 原因分析&#xff1a; 因为使用的gradio版本过高&#xff0c;使用较低版本。 pip install gradio3.49.0 会有提示IMPORTANT: You are using gradio version 3.49.…

【AIGC】从技术趋势深度发掘AIGC行业的商业化进展,给你一个AIGC商业落地产业

前言 Artificial Intelligence Generated Content&#xff09;行业逐渐崭露头角&#xff0c;成为科技领域的一大热点。那么&#xff0c;在当前这个时间点&#xff0c;AIGC行业是否适合进入呢&#xff1f;本文将从行业发展阶段、商业化进展、技术趋势等多个维度进行探讨&#x…

STM32F103点亮LED灯和实现LED闪烁(标准库)

芯片&#xff1a;STM32F103GCT6 原理图&#xff1a; 实现&#xff1a;PC6——闪烁&#xff0c;PC7——常亮 main.c //头文件 #include "stm32f10x.h" #include "user.h"//全局变量 uint8_t g_1s_flag 0; uint8_t g_uart1_rx_done 0;uint32_t g_ms 0…

免交互简单操作

免交互 交互&#xff1a;我们发出指令控制程序的运行&#xff0c;程序在接收到指令后按照指令的效果作出对应的反应 免交互&#xff1a;间接的&#xff0c;通过第三方的方式把指令传给程序&#xff0c;不用直接下达指令 Here Document免交互 这是命令行格式&#xff0c;也可…

PointNet数据预处理+网络训练

PointNet数据预处理网络训练 数据预处理分类网络的训练分割网络训练分类和分割的结果 数据预处理 数据预处理&#xff0c;这里仅介绍一个shapenetdataset&#xff1b; class ShapeNetDataset(data.Dataset):def __init__(self,root,npoints2500,classificationFalse,class_ch…

没有手机怎么办呐!高考成绩出来了:请不要吹灭别人的灯——早读(逆天打工人爬取热门微信文章解读)

结婚的时候红包随礼随多少呢 引言Python 代码第一篇 洞见 高考成绩出来了&#xff1a;请不要吹灭别人的灯第二篇结尾 为什么是这个标题呢&#xff1f; 是因为摸鱼看足球直播 主播好兄弟结婚 他老婆问他要红包 引言 今天早上停电了 大概是在3点多的时候 我本身一直都没有开空调…

SAP-SD-修改字段描述

在销售订单中,想修改某字段名的描述,以客户组12为例,如下图 现在想把这个字段修改为客户组1,选择-F1 双击“数据元素” 双击 域 转到-翻译

移动硬盘删除的文件能恢复吗?一文揭晓答案!

“我很喜欢把重要的文件都存储到移动硬盘中&#xff0c;但今天在操作时误删了比较重要的一些文件。大家有什么方法可以帮我恢复里面的重要数据吗&#xff1f;” 在数字世界的浩瀚宇宙中&#xff0c;我们的每一份文件、每一张照片、每一个视频&#xff0c;都是一段珍贵的记忆&am…

修改 Linux 终端提示符的色彩与字体

1、引言 Linux 终端是许多开发者和系统管理员每天工作的主要工具之一。但你是否曾留意过那个位于命令行开头的提示符&#xff1f;是不是觉得它有点单调&#xff1f;别担心&#xff0c;本文将介绍如何通过修改提示符的颜色和字体&#xff0c;为你的 Linux 终端增添一抹独特的色…

昇思25天学习打卡营第二天|张量 Tensor

背景 华为组织了昇思25天学习学习营&#xff0c;提供免费算力&#xff0c;算力支持是昇腾Ascend 910芯片96G内存&#xff0c;很给力。 第一天的学习内容可以阅读文章&#xff1a; 昇思25天学习打卡营第一天|快速入门 学习内容 今天的学习内容是张量。如果线性代数学的好的同…

python - 运算符 / 条件语句 / 数字类型

一.运算符 >>> 5<3 False >>> 5<3 False >>> 5>3 True >>> 5>3 True >>> 53 False >>> 5!3 True 与操作and&#xff1a; >>> 5<3 and 2<4 False >>> 5>3 and 2<4 True 二…

解锁高效办公:ONLYOFFICE版本8.1新功能揭秘与个人使用体验

文章目录 &#x1f4af;ONLYOFFICE 桌面编辑器 8.1 ✍1 新增功能介绍✍2 轻松编辑器PDF文件&#x1f353;2.1 PDF新增编辑器操作&#x1f353;2.2 PDF新增表单操作 ✍3 用幻灯片版式快速修改幻灯片✍4 无缝切换文档编辑、审阅和查看模式✍5 改进从右至左语言的支持 & 新的本…

景联文科技构建高质量多轮对话数据库,赋能AI交互新飞跃

近年来&#xff0c;大语言模型的发展极大推动了自然语言处理领域的进步&#xff0c;大语言模型正引领智能对话领域进入一个全新时代&#xff0c;不仅提升了对话体验的自然度和效率&#xff0c;也为探索更加人性化、智能化的交互方式开辟了道路。 景联文科技作为大语言模型数据服…

【PB案例学习笔记】-24创建一个窗口图形菜单

写在前面 这是PB案例学习笔记系列文章的第24篇&#xff0c;该系列文章适合具有一定PB基础的读者。 通过一个个由浅入深的编程实战案例学习&#xff0c;提高编程技巧&#xff0c;以保证小伙伴们能应付公司的各种开发需求。 文章中设计到的源码&#xff0c;小凡都上传到了gite…

【面试干货】Java中new与clone操作对象的比较

【面试干货】Java中new与clone操作对象的比较 1、new操作符创建对象的过程2、clone方法创建对象的过程3、总结 &#x1f496;The Begin&#x1f496;点点关注&#xff0c;收藏不迷路&#x1f496; 1、new操作符创建对象的过程 new操作符在Java中用于创建对象&#xff0c;并执行…

MySQL索引优化解决方案--索引优化(4)

排序优化 尽量避免使用Using FileSort方式排序。order by语句使用索引最左前列或使用where子句与order by子句条件组合满足索引最左前列。where子句中如果出现索引范围查询会导致order by索引失效。 优化案例 联表查询优化 分组查询优化 慢查询日志

简约的服务器监控工具Ward

什么是 Ward &#xff1f; Ward 是一个简单简约的服务器监控工具。 Ward 支持自适应设计系统。此外&#xff0c;它还支持深色主题。它仅显示主要信息&#xff0c;如果您想查看漂亮的仪表板而不是查看一堆数字和图表&#xff0c;则可以使用它。 Ward 在所有流行的操作系统上都能…

SiLM585x系列SiLM5851NHCG-DG一款具有分离的管脚输出 单通道隔离驱动器 拥有强劲的驱动能力

SiLM585x系列SiLM5851NHCG-DG是一款单通道隔离驱动器&#xff0c;具有分离的管脚输出&#xff0c;提供3.0A源电流和6.0A灌电流。主动保护功能包括退饱和过流检测、UVLO、隔离故障报警和 2.5A 米勒钳位。输入侧电源的工作电压为3V至5.5V&#xff0c;输出侧电源的工作电压范围为1…

深度学习项目实例(一)—— 实时AI换脸项目

一、前言 人工智能&#xff08;AI&#xff09;技术的快速发展为各个领域带来了革命性的变化&#xff0c;其中之一就是人脸识别与图像处理技术。在这之中&#xff0c;AI换脸技术尤其引人注目。这种技术不仅在娱乐行业中得到广泛应用&#xff0c;如电影制作、视频特效等&#xf…

想要用tween实现相机的移动,three.js渲染的canvas画布上相机位置一点没动,如何解决??

&#x1f3c6;本文收录于「Bug调优」专栏&#xff0c;主要记录项目实战过程中的Bug之前因后果及提供真实有效的解决方案&#xff0c;希望能够助你一臂之力&#xff0c;帮你早日登顶实现财富自由&#x1f680;&#xff1b;同时&#xff0c;欢迎大家关注&&收藏&&…