Java大师成长计划之第16天:高级并发工具类
📢 友情提示:
本文由银河易创AI(https://ai.eaigx.com)平台gpt-4o-mini模型辅助创作完成,旨在提供灵感参考与技术分享,文中关键数据、代码与结论建议通过官方渠道验证。
在现代Java应用中,处理并发问题是确保系统性能和可扩展性的关键。在前面的学习中,我们已经了解了Java中的基本线程操作和线程安全机制。本篇文章将深入探讨Java的高级并发工具类,包括Executor框架、Future和Fork/Join框架,以帮助你更好地管理并发任务。
一. Executor框架
1.1 什么是Executor框架?
Executor框架是Java在java.util.concurrent
包中提供的一套用于管理并发任务的工具。它是基于生产者—消费者模式设计的,主要目的是通过线程池来有效管理线程的生命周期,简化线程的创建、管理和调度。与传统的创建和管理线程的方式不同,Executor框架让开发者不需要手动管理线程,而是通过提交任务来进行调度和执行。通过合理使用线程池,Executor框架能够显著提升应用程序的性能,减少线程的创建和销毁开销,避免资源的浪费。
在没有线程池的情况下,每次需要执行任务时都要手动创建线程,这会导致创建大量线程的开销和管理困难。而Executor框架提供了一种统一的方式来提交任务并执行,开发者只需关心任务的提交和管理,而不必关注具体的线程创建与销毁的细节。
1.2 Executor框架的核心接口
Executor框架主要由以下几种接口组成:
-
Executor接口:它是Executor框架的顶层接口,定义了一个方法
execute(Runnable command)
,用于提交一个Runnable任务。通过这个接口,线程池能够执行传递给它的任务。 -
ExecutorService接口:它继承了Executor接口,并添加了更多与任务生命周期相关的方法,比如任务的提交、任务的取消等。
ExecutorService
接口提供了更强大的功能,支持提交Callable
任务和获取任务的执行结果。它还包含了管理线程池生命周期的方法,如shutdown()
。 -
ScheduledExecutorService接口:它继承了
ExecutorService
接口,并提供了对定时任务和周期性任务的支持。开发者可以使用它调度任务在指定时间执行,或定期执行。
1.3 Executor的实现类
Java提供了多个Executor
接口的实现类,最常用的实现类有:
-
ThreadPoolExecutor:这是Executor框架中最强大且灵活的线程池实现类。它支持动态调整线程池的大小,可以根据需要创建和管理线程。
ThreadPoolExecutor
提供了丰富的配置选项,适合于大多数并发任务的管理。 -
ScheduledThreadPoolExecutor:这是
ScheduledExecutorService
的实现类,支持定时和周期性执行任务。它比Timer
类更加灵活,并能更好地处理多线程场景中的异常。 -
Executors:这是一个工厂类,提供了静态方法来创建不同类型的线程池,如固定大小线程池、单线程池和缓存线程池等。通过这个类,开发者能够更轻松地创建和配置线程池。
1.4 使用Executor框架创建线程池
Executor框架通过线程池来管理和调度任务。线程池的使用能够有效减少线程的创建和销毁开销,且能提供任务调度、执行、监控等功能。Java提供了一个工厂类Executors
,通过它可以快速创建不同类型的线程池。
1.4.1 创建固定大小线程池
import java.util.concurrent.*;public class ExecutorDemo {public static void main(String[] args) {// 创建一个固定大小的线程池ExecutorService executor = Executors.newFixedThreadPool(2);// 提交任务for (int i = 0; i < 5; i++) {executor.submit(() -> {System.out.println(Thread.currentThread().getName() + " is executing a task.");});}// 关闭线程池executor.shutdown();}
}
在这个例子中,我们创建了一个固定大小的线程池,池中的线程数为2。即使提交了5个任务,线程池中只有两个线程可以同时执行任务。任务的其余部分将被排队等待线程空闲。
1.4.2 创建单线程池
import java.util.concurrent.*;public class SingleThreadExecutorDemo {public static void main(String[] args) {// 创建一个只有一个线程的线程池ExecutorService executor = Executors.newSingleThreadExecutor();// 提交任务for (int i = 0; i < 5; i++) {executor.submit(() -> {System.out.println(Thread.currentThread().getName() + " is executing a task.");});}// 关闭线程池executor.shutdown();}
}
newSingleThreadExecutor()
方法创建一个只包含一个线程的线程池。这种类型的线程池常用于需要保证任务按顺序执行的场景,线程池中的任务会顺序执行,并且不会并行执行。
1.4.3 创建可缓存线程池
import java.util.concurrent.*;public class CachedThreadPoolDemo {public static void main(String[] args) {// 创建一个可缓存的线程池ExecutorService executor = Executors.newCachedThreadPool();// 提交任务for (int i = 0; i < 5; i++) {executor.submit(() -> {System.out.println(Thread.currentThread().getName() + " is executing a task.");});}// 关闭线程池executor.shutdown();}
}
newCachedThreadPool()
方法创建一个可缓存的线程池。线程池会根据任务的数量动态调整线程池的大小。如果有空闲线程,线程池会复用这些线程,否则会创建新线程来执行任务。当线程池中的线程长时间没有任务执行时,它们会被回收。
1.4.4 创建定时任务线程池
import java.util.concurrent.*;public class ScheduledExecutorServiceDemo {public static void main(String[] args) {// 创建一个定时任务线程池ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);// 提交定时任务:延迟1秒后执行executor.schedule(() -> {System.out.println(Thread.currentThread().getName() + " is executing a scheduled task.");}, 1, TimeUnit.SECONDS);// 提交周期性任务:每2秒执行一次executor.scheduleAtFixedRate(() -> {System.out.println(Thread.currentThread().getName() + " is executing a periodic task.");}, 0, 2, TimeUnit.SECONDS);}
}
newScheduledThreadPool()
方法用于创建一个可以执行定时任务和周期性任务的线程池。schedule()
方法用于提交延迟任务,而scheduleAtFixedRate()
方法用于提交周期性任务。
1.5 线程池的管理
线程池在执行任务时需要合理配置其参数,特别是线程池的大小、任务队列的类型、线程的最大空闲时间等。在使用线程池时,我们通常会面临以下几个问题:
-
线程池的大小:线程池的大小应根据系统的负载和任务的特点来合理配置。一般情况下,线程池的大小可以通过CPU核心数来确定。例如,
Runtime.getRuntime().availableProcessors()
方法可以返回当前系统的CPU核心数。对于I/O密集型任务,线程池可以配置为稍大于CPU核心数;而对于CPU密集型任务,线程池的大小通常不需要超过CPU核心数。 -
任务队列:线程池的任务队列用于存储等待执行的任务。常见的任务队列有:
- 无界队列(LinkedBlockingQueue):当线程池中的线程数达到最大值时,任务会被无限制地加入队列。
- 有界队列(ArrayBlockingQueue):有界队列限制了队列的大小,任务队列满时,新的任务将被拒绝。
- 优先级队列(PriorityBlockingQueue):任务会根据优先级进行排序。
-
拒绝策略:当线程池中的线程和任务队列都被占满时,可以选择任务的拒绝策略。常见的拒绝策略有:
- AbortPolicy:直接抛出异常(默认策略)。
- CallerRunsPolicy:由调用者线程来执行该任务。
- DiscardPolicy:直接丢弃任务。
- DiscardOldestPolicy:丢弃队列中最旧的任务。
ThreadPoolExecutor executor = new ThreadPoolExecutor(2, // corePoolSize4, // maximumPoolSize60, // keepAliveTimeTimeUnit.SECONDS, // time unitnew ArrayBlockingQueue<>(10), // work queuenew ThreadPoolExecutor.CallerRunsPolicy() // rejection policy
);
1.6 总结
Executor框架提供了一个非常强大而灵活的机制来管理并发任务。通过使用不同类型的线程池,开发者可以根据任务的特点,灵活地调度和执行任务。同时,Executor框架不仅简化了线程管理,也有效避免了手动管理线程池时的资源浪费和复杂性。随着你对线程池及其配置的不断熟悉,你将能够更好地应对多线程编程中的各种挑战。
二. Future接口
2.1 什么是Future?
Future
接口是Java中的一个重要接口,位于java.util.concurrent
包中,代表一个异步计算的结果。它提供了一种机制,使得开发者可以在任务执行完成后获取结果,同时还可以检查任务的完成状态或处理异常。Future
接口的设计使得多线程编程变得更加灵活和高效。
在并行编程中,通常会遇到需要在某个任务执行完成后获取其计算结果的场景。使用Future
接口,开发者不仅可以提交并行执行的任务,还可以在需要的时候安全地获取这些任务的结果或处理异常。
2.2 Future接口的主要方法
Future
接口定义了一些关键的方法,帮助开发者管理异步任务的执行。以下是Future接口
中最常用的方法:
-
boolean cancel(boolean mayInterruptIfRunning)
:尝试取消任务的执行。如果任务已被执行或已完成,则无法取消。mayInterruptIfRunning
参数指示是否中断正在执行的任务。 -
boolean isCancelled()
:检查任务是否已被取消。 -
boolean isDone()
:检查任务是否已完成。任务可能是通过正常完成、异常或被取消而完成。 -
V get()
throws InterruptedException, ExecutionException:获取任务的结果。如果任务尚未完成,该方法会阻塞,直到结果可用。 -
V get(long timeout, TimeUnit unit)
throws InterruptedException, ExecutionException, TimeoutException:获取任务的结果,并设置超时。如果在指定时间内未完成,则抛出TimeoutException
。
2.3 提交任务并获取结果
在Executor框架中,使用submit()
方法可以提交一个Callable
任务,并返回一个Future
对象。通过这个Future
对象,可以在任务执行完成后获取结果或处理异常。
示例:使用Future获取任务结果
import java.util.concurrent.*;public class FutureResultExample {public static void main(String[] args) {ExecutorService executor = Executors.newFixedThreadPool(1);// 提交一个Callable任务Future<Integer> future = executor.submit(() -> {// 模拟长时间任务Thread.sleep(2000);return 42; // 返回结果});// 在这里可以执行其他操作System.out.println("Task submitted, doing other things...");try {// 获取任务结果(阻塞式)Integer result = future.get(); // 这会等待任务完成System.out.println("Task result: " + result);} catch (InterruptedException | ExecutionException e) {e.printStackTrace();} finally {executor.shutdown(); // 关闭线程池}}
}
在这个示例中,我们提交了一个Callable
任务,计算结果的值为42。调用future.get()
时,如果任务未完成,当前线程会被阻塞,直到任务完成并返回结果。在这段时间内,我们仍然可以执行其他操作。
2.4 Future的常用用途
Future
接口可以用于多种场景,以下是一些典型的用途:
-
异步任务执行:
Future
非常适合于需要在后台线程中执行耗时操作的场景,比如文件下载、网络请求等。 -
批量处理:在需要处理大量数据时,可以使用
Future
提交多个异步任务,并在所有任务完成后获取结果。 -
任务取消:通过
Future.cancel()
方法,可以尝试取消正在执行的任务,这在处理长时间运行的操作时非常有用。 -
超时控制:使用
get(long timeout, TimeUnit unit)
方法,可以指定获取结果的超时时间,从而避免线程长时间阻塞。
2.5 示例:取消Future任务
import java.util.concurrent.*;public class CancelFutureExample {public static void main(String[] args) throws InterruptedException {ExecutorService executor = Executors.newFixedThreadPool(1);// 提交一个长时间运行的任务Future<Integer> future = executor.submit(() -> {try {Thread.sleep(5000); // 模拟长时间任务} catch (InterruptedException e) {System.out.println("Task was interrupted");return null; // 返回 null 表示任务中断}return 42; // 返回结果});// 等待一段时间后尝试取消任务Thread.sleep(1000);boolean canceled = future.cancel(true); // 请求取消System.out.println("Task canceled: " + canceled);try {// 尝试获取任务结果Integer result = future.get(); // 可能会抛出异常System.out.println("Task result: " + result);} catch (CancellationException e) {System.out.println("Task was canceled: " + e.getMessage());} catch (ExecutionException e) {System.out.println("Task encountered an exception: " + e.getCause());}executor.shutdown(); // 关闭线程池}
}
在这个示例中,我们提交了一个模拟长时间运行的任务。我们在1秒后尝试取消这个任务。调用future.cancel(true)
会请求取消任务,如果任务正在执行且可以中断,任务将在下一个检查点被中断。我们可以通过异常处理来捕获任务取消或执行中的异常。
2.6 总结
Future
接口为Java中的异步计算提供了强大的支持,允许开发者轻松管理和获取异步任务的结果。通过合理使用Future
,可以提高程序的响应能力和性能,特别是在处理耗时的操作或需要并发执行多个任务的场合。理解Future
的使用和特点,将使你在并发编程中游刃有余。
三. Fork/Join框架
3.1 什么是Fork/Join框架?
Fork/Join框架是Java 7引入的一种并行编程模型,旨在充分利用多核处理器的能力。该框架采用了分而治之的设计思想,将一个复杂的任务递归地分解成多个小任务并行执行,最终合并结果。Fork/Join框架位于java.util.concurrent
包中,主要由ForkJoinPool
、ForkJoinTask
及其子类RecursiveTask
和RecursiveAction
构成。
通过Fork/Join框架,开发者可以高效地处理需要大量计算的任务,特别是在处理大规模的数据集或计算问题时。由于其底层实现了工作窃取算法,因此它能够在任务执行过程中动态地调整线程的利用率,从而提高程序的执行效率。
3.2 ForkJoinPool
ForkJoinPool
是Fork/Join框架的核心组件,负责管理和调度Fork/Join任务。与传统的线程池不同,Fork/Join框架采用了工作窃取算法,这意味着空闲的工作线程可以从其他忙碌线程的任务队列中“窃取”任务以执行。这种设计极大地提高了多核CPU的利用率,避免了线程的长时间空闲。
3.2.1 ForkJoinPool的基本特性
- 工作窃取:每个工作线程都有一个双端队列,用于存储待处理的任务。当线程的任务队列为空时,它会从其他线程的队列中窃取任务执行。
- 分层结构:Fork/Join框架支持递归任务的分层结构,能够自动调整任务的分配和执行策略。
- 可调的并行度:通过设置并行度,开发者可以控制Fork/Join框架的性能表现,适应不同的应用场景。
3.3 ForkJoinTask
ForkJoinTask
是Fork/Join框架中的抽象类,表示可以在ForkJoinPool
中执行的任务。它是异步计算的基础,主要有两种具体的实现:
- RecursiveTask<V>:用于在任务执行后返回结果的子类,适合有结果返回的计算任务。
- RecursiveAction:用于不返回结果的子类,适合只执行操作的任务。
3.4 使用RecursiveTask进行任务分解
在Fork/Join框架中,通常使用RecursiveTask
来实现可分解的计算任务。开发者需要重写compute()
方法,在该方法中定义任务的分解逻辑和结果合并的过程。
示例:使用Fork/Join框架计算斐波那契数
import java.util.concurrent.RecursiveTask;
import java.util.concurrent.ForkJoinPool;public class Fibonacci extends RecursiveTask<Integer> {private final int n;public Fibonacci(int n) {this.n = n;}@Overrideprotected Integer compute() {if (n <= 1) {return n;}// 将任务分解为两个子任务Fibonacci f1 = new Fibonacci(n - 1);Fibonacci f2 = new Fibonacci(n - 2);// 异步计算第一个子任务f1.fork();// 计算第二个子任务int resultF2 = f2.compute();// 等待第一个子任务完成并获取结果int resultF1 = f1.join();// 返回最终结果return resultF1 + resultF2;}public static void main(String[] args) {ForkJoinPool pool = new ForkJoinPool();int n = 10; // 计算第10个斐波那契数int result = pool.invoke(new Fibonacci(n)); // 提交任务System.out.println("Fibonacci of " + n + " is " + result);}
}
在这个例子中,我们实现了一个计算斐波那契数的RecursiveTask
。compute()
方法中,当输入参数n
小于等于1时,直接返回结果;否则,将任务分解为两个子任务,然后异步计算第一个子任务,最后计算第二个子任务,并合并结果。
3.4.1 任务分解与合并
Fork/Join框架的核心思想是“分而治之”,即将一个大任务分解为多个小任务并行处理。在执行compute()
时,开发者需要决定何时分解任务以及如何合并结果。
- 任务分解:通过递归地创建子任务,任务可以被逐步分解到足够小且易于计算的程度。
- 结果合并:使用
join()
方法等待子任务完成并获取结果,合并所有子任务的结果以得到最终的答案。
3.5 使用RecursiveAction进行并行操作
当任务不需要返回结果时,可以使用RecursiveAction
类。RecursiveAction
的使用方式与RecursiveTask
类似,但不涉及结果的返回。
示例:使用Fork/Join框架进行数组求和
import java.util.concurrent.RecursiveAction;
import java.util.concurrent.ForkJoinPool;public class ArraySum extends RecursiveAction {private final int[] array;private final int start;private final int end;private static final int THRESHOLD = 10; // 阈值public ArraySum(int[] array, int start, int end) {this.array = array;this.start = start;this.end = end;}@Overrideprotected void compute() {if (end - start <= THRESHOLD) {// 直接计算小块的和int sum = 0;for (int i = start; i < end; i++) {sum += array[i];}System.out.println("Sum from " + start + " to " + end + " is: " + sum);} else {// 分解任务int mid = (start + end) / 2;ArraySum leftTask = new ArraySum(array, start, mid);ArraySum rightTask = new ArraySum(array, mid, end);invokeAll(leftTask, rightTask); // 同时执行两个子任务}}public static void main(String[] args) {int[] array = new int[100];for (int i = 0; i < array.length; i++) {array[i] = i + 1; // 填充数组}ForkJoinPool pool = new ForkJoinPool();pool.invoke(new ArraySum(array, 0, array.length)); // 提交任务}
}
在这个例子中,我们实现了一个RecursiveAction
来计算数组的和。通过设置一个阈值,当任务的大小小于等于THRESHOLD
时,直接计算和;否则,将任务分解为两个子任务并并行处理。
3.6 Fork/Join框架的优势
- 高效利用多核处理器:Fork/Join框架的工作窃取算法能够充分利用多核CPU的处理能力,使得任务执行更加高效。
- 简化并行编程:通过提供简单的API,Fork/Join框架最大限度地简化了并行编程的复杂性,允许开发者专注于任务的分解和合并。
- 动态调整任务:由于采用工作窃取算法,Fork/Join框架能够动态调整并发任务的执行,从而提高系统的响应能力和处理效率。
3.7 总结
Fork/Join框架为Java开发者提供了一种强大的工具,能够以简洁的方式实现高效的并行处理。通过合理使用ForkJoinPool
、RecursiveTask
和RecursiveAction
,开发者可以将复杂的计算任务分解为小任务并行执行,从而显著提高程序的性能和响应能力。掌握Fork/Join框架将使你在处理大规模计算问题时游刃有余,充分发挥多核处理器的优势。
四. 总结
在本篇文章中,我们深入探讨了Java中的高级并发工具类,包括Executor框架、Future接口和Fork/Join框架。通过合理使用这些工具,我们可以更高效地管理线程和并发任务,提高应用程序的性能和响应能力。随着对并发编程的深入理解,你将能够设计出更加高效和可靠的Java应用程序。
继续关注我们的Java大师成长计划,接下来的内容将为你带来更多有趣和实用的技术!
相关文章:
Java大师成长计划之第16天:高级并发工具类
📢 友情提示: 本文由银河易创AI(https://ai.eaigx.com)平台gpt-4o-mini模型辅助创作完成,旨在提供灵感参考与技术分享,文中关键数据、代码与结论建议通过官方渠道验证。 在现代Java应用中,处理并…...
lambda 表达式
C 的 lambda 表达式 是一种轻量、内联的函数对象写法,广泛用于标准算法、自定义回调、事件响应等场景。它简洁且强大。以下将系统、详细地讲解 lambda 的语法、捕获规则、应用技巧和实际使用场景。 🧠 一、基本语法 [捕获列表](参数列表) -> 返回类型…...

Edu教育邮箱申请2025年5月
各位好,这里是aigc创意人竹相左边 如你所见,这里是第3部分 现在是选择大学的学科专业 选专业的时候记得考虑一下当前的时间日期。 比如现在是夏天,所以你选秋天入学是合理的。...
JVM内存模型深度解剖:分代策略、元空间与GC调优实战
堆 堆是Java虚拟机(JVM)内存管理的核心区域,其物理存储可能分散于不同内存页,但逻辑上被视为连续的线性空间。作为JVM启动时创建的第一个内存区域,堆承载着几乎所有的对象实例和数组对象(极少数通过逃逸分…...

STM32-TIM定时中断(6)
目录 一、TIM介绍 1、TIM简介 2、定时器类型 3、基本定时器 4、通用定时器 5、定时中断基本结构 6、时基单元的时序 (1)预分频器时序 (2)计数器时序 7、RCC时钟树 二、定时器输出比较功能(PWM) …...
微信小程序地图缩放scale隐性bug
bug1 在真机环境下通过this.mapCtx.getScale获取当前地图的缩放等级带小数, 当设置scale带小数时,地图会先执行到缩放到带小数的缩放等级,然后会再次缩放取整的缩放等级(具体向上取整还是向下取整未知,两种情况都观察…...
window 显示驱动开发-配置内存段类型
视频内存管理器(VidMm)和显示硬件仅支持某些类型的内存段。 因此,内核模式显示微型端口驱动程序(KMD)只能配置这些类型的段。 KMD 可以配置内存空间段和光圈空间段,其中不同: 内存空间段由保存…...

Modbus RTU 详解 + FreeMODBUS移植(附项目源码)
文章目录 前言一、Modbus RTU1.1 通信方式1.2 模式特点1.3 数据模型1.4 常用功能码说明1.5 异常响应码1.6 通信帧格式1.6.1 示例一:读取保持寄存器(功能码 0x03)1.6.2 示例二:写单个线圈(功能码 0x05)1.6.3…...

对称加密算法(AES、ChaCha20和SM4)Python实现——密码学基础(Python出现No module named “Crypto” 解决方案)
文章目录 一、对称加密算法基础1.1 对称加密算法的基本原理1.2 对称加密的主要工作模式 二、AES加密算法详解2.1 AES基本介绍2.2 AES加密过程2.3 Python中实现AES加密Python出现No module named “Crypto” 解决方案 2.4 AES的安全考量 三、ChaCha20加密算法3.1 ChaCha20基本介…...
JWT原理及工作流程详解
JSON Web Token(JWT)是一种开放标准(RFC 7519),用于在各方之间安全传输信息。其核心原理是通过结构化、签名或加密的JSON对象实现无状态身份验证和授权。以下是JWT的工作原理和关键组成部分: 1. JWT结构 J…...

【软件设计师:存储】16.计算机存储系统
一、主存储器 存储器是计算机系统中的记忆设备,用来存放程序和数据。 计算机中全部信息,包括输入的原始数据、计算机程序、中间运 行结果和最终运行结果都保存在存储器中。 存储器分为: 寄存器Cache(高速缓冲存储器)主存储器辅存储器一、存储器的存取方式 二、存储器的性…...
【Part 2安卓原生360°VR播放器开发实战】第三节|实现VR视频播放与时间轴同步控制
《VR 360全景视频开发》专栏 将带你深入探索从全景视频制作到Unity眼镜端应用开发的全流程技术。专栏内容涵盖安卓原生VR播放器开发、Unity VR视频渲染与手势交互、360全景视频制作与优化,以及高分辨率视频性能优化等实战技巧。 📝 希望通过这个专栏&am…...

WebRTC通信原理与流程
1、服务器与协议相关 1.1 STUN服务器 图1.1.1 STUN服务器在通信中的位置图 1.1.1 STUN服务简介 STUN(Session Traversal Utilities for NAT,NAT会话穿越应用程序)是一种网络协议,它允许位于NAT(或多重 NAT)…...

Java版ERP管理系统源码(springboot+VUE+Uniapp)
ERP系统是企业资源计划(Enterprise Resource Planning)系统的缩写,它是一种集成的软件解决方案,用于协调和管理企业内各种关键业务流程和功能,如财务、供应链、生产、人力资源等。它的目标是帮助企业实现资源的高效利用…...

Redis总结(六)redis持久化
本文将简单介绍redis持久化的两种方式 redis提供了两种不同级别的持久化方式: RDB持久化方式能够在指定的时间间隔能对你的数据进行快照存储.AOF持久化方式记录每次对服务器写的操作,当服务器重启的时候会重新执行这些命令来恢复原始的数据,AOF命令以redis协议追加保…...
使用FastAPI微服务在AWS EKS中构建上下文增强型AI问答系统
系统概述 本文介绍如何使用FastAPI在AWS Elastic Kubernetes Service (EKS)上构建一个由多个微服务组成的AI问答系统。该系统能够接收用户输入的提示(prompt),通过调用其他微服务从AWS ElastiCache on Redis和Amazon DynamoDB获取相关上下文,然后利用AW…...

PMIC电源管理模块的PCB设计
目录 PMU模块简介 PMU的PCB设计 PMU模块简介 PMIC(电源管理集成电路)是现代电子设备的核心模块,负责高效协调多路电源的转换、分配与监控。它通过集成DC-DC降压/升压、LDO线性稳压、电池充电管理、功耗状态切换等功能,替代传统分…...
正大视角下的结构交易节奏:如何借助数据捕捉关键转折
正大视角下的结构交易节奏:如何借助数据捕捉关键转折 在日常的交易结构研究中,节奏与分型常常被误解为“预测工具”,实则更应作为状态识别的参考。正大团队在模型演化过程中提出了“节奏-结构对齐”的分析方式,通过数据驱动来判断…...

华为云Flexus+DeepSeek征文|DeepSeek-V3商用服务开通教程
目录 DeepSeek-V3/R1商用服务开通使用感受 DeepSeek-V3/R1商用服务开通 1、首先需要访问ModelArts Studio_MaaS_大模型即服务_华为云 2、在网站右上角登陆自己的华为云账号,如果没有华为云账号的话,则需要自己先注册一个。 3、接着点击ModelArts Stu…...
STM32F103RC中ADC1和ADC2通道复用
以下是STM32F103RC中ADC1和ADC2通道复用的示意图及文字说明,帮助直观理解这种共享关系: ADC1/ADC2引脚复用示意图 GPIO引脚 ADC1通道 ADC2通道 ┌─────────┐ ┌─────────┐ ┌─────────┐ │ PA0 ├─…...

Qt—鼠标移动事件的趣味小程序:会移动的按钮
1.项目目标 本次根据Qt的鼠标移动事件实现一个趣味小程序:当鼠标移动到按钮时,按钮就会随机出现在置,以至于根本点击不到按钮。 2.项目步骤 首先现在ui界面设计控件(也可以用代码的方式创建,就不多说了) 第一个按钮不需…...

鞋样设计软件
Sxy 64鞋样设计软件是一款专业级鞋类设计工具 专为鞋业设计师与制鞋企业开发 该软件提供全面的鞋样设计功能 包括二维开版 三维建模 放码排料等核心模块 支持从草图构思到成品输出的完整设计流程 内置丰富的鞋型数据库与部件库 可快速生成各种鞋款模板 软件采用智能放码技术 精…...

LeRobot 项目部署运行逻辑(六)——visualize_dataset_html.py/visualize_dataset.py
可视化脚本包括了两个方法:远程下载 huggingface 上的数据集和使用本地数据集 脚本主要使用两个: 目前来说,ACT 采集训练用的是统一时间长度的数据集,此外,这两个脚本最大的问题在于不能裁剪,这也是比较好…...

Windows Server 2025开启GPU分区(GPU-P)部署DoraCloud云桌面
本文描述在ShareStation工作站虚拟化方案的部署过程。 将服务器上部署 Windows Server、DoraCloud,并创建带有vGPU的虚拟桌面。 GPU分区技术介绍 GPU-P(GPU Partitioning) 是微软在 Windows 虚拟化平台(如 Hyper-V)中…...

TCP套接字通信核心要点
TCP套接字通信核心要点 通信模型架构 客户端-服务端模型 CS架构:客户端发起请求,服务端响应和处理请求双向通道:建立连接后实现全双工通信 服务端搭建流程 核心步骤 创建套接字 int server socket(AF_INET, SOCK_STREAM, 0); 参数说明&am…...

【C】初阶数据结构15 -- 计数排序与稳定性分析
本文主要讲解七大排序算法之外的另一种排序算法 -- 计数排序 目录 1 计数排序 1) 算法思想 2) 代码 3) 时间复杂度与空间复杂度分析 (1) 时间复杂度 (2) 空间复杂度 4) 计…...

高性能Python Web 框架--FastAPI 学习「基础 → 进阶 → 生产级」
以下是针对 FastAPI 的保姆级教程,包含核心概念、完整案例和关键注意事项,采用「基础 → 进阶 → 生产级」的三阶段教学法: 一、FastAPI介绍 FastAPI 是一个现代化的、高性能的 Python Web 框架,专门用于构建 APIs(应…...

Qt QML自定义LIstView
QML ListView组合拳做列表,代码不可直接复制使用,需要小改 先上图看效果 样式1 样式2 样式3 原理:操作:技术点:代码片段: 先上图看效果 样式1 三个表格组合成要给,上下滚动时,三个同时滚动&am…...

C++进阶--红黑树的实现
文章目录 红黑树的实现红黑树的概念红黑树的规则红黑树的效率 红黑树的实现红黑树的结构红黑树的插入变色单旋(变色)双旋(变色) 红黑树的查找红黑树的验证 总结:结语 很高兴和大家见面,给生活加点impetus&a…...

WPF之值转换器
文章目录 目录什么是值转换器IValueConverter接口Convert方法ConvertBack方法 创建和使用值转换器定义转换器类在XAML中使用转换器转换器参数(ConverterParameter) 常用转换器实现布尔值转可见性(BoolToVisibilityConverter)数值转…...