当前位置: 首页 > news >正文

线程池以及详解使用@Async注解异步处理方法

目录

一.什么是线程池:

二.使用线程池的好处:

三.线程池的使用场景:

四.使用线程池来提高Springboot项目的并发处理能力:

1.在application.yml配置文件中配置:

2.定义配置类来接受配置文件内的属性值:

3.启用异步支持:

4.实例:

 五.详细解析@Async注解的使用:

1.@Async注解作用:

2.@Async注解的调用过程:

3.@Async注解使用:

(1)启用异步支持:

 (2)定义异步方法:

(3)调用异步方法:

六.CompleteableFuture返回类型的使用:

1.基本使用:

(1)通过创建 CompleteableFuture 对象来创建异步任务:

(2)获取异步方法的结果:

2.链式编程:

(1)thenApply():处理结果并返回新的值

(2)thenAccept():处理结果但不返回值

(3)thenRun():完成后执行另一个操作,但不关心结果

3.组合多个异步任务进行处理:

(1)thenCombine() – 组合两个独立任务的结果

(2)thenCompose() – 链式依赖

(3)allOf() – 等待多个任务全部完成

(4)anyOf() – 任意一个完成

4.异常处理:

(1)exceptionally() – 捕获并处理异常

(2)handle() – 处理正常和异常情况

(3)whenComplete() – 完成后执行处理,无论是否有异常

5.超时处理:

(1)orTimeout() – 设置超时时间

(2)completeOnTimeout() – 超时后返回默认值

6.细节注意:

(1)避免阻塞:

(2)处理异常:

(3)线程池优化:


一.什么是线程池:

线程池 是一种用于管理和控制多个工作线程的技术,常用于处理并发任务。线程池的主要作用是避免在执行并发任务时频繁创建和销毁线程,从而提升系统的性能和资源利用率。线程池会维护一定数量的线程,当需要执行任务时,会将任务交给线程池中的空闲线程去执行,而不需要为每个任务创建新的线程。

二.使用线程池的好处:

  • 降低资源消耗:通过复用已经创建的线程,减少线程创建和销毁的开销,尤其在高并发情况下,这一点尤为明显。

  • 提高响应速度:线程池的线程可以在任务到来时立即执行任务,而不必等待线程创建,减少了响应时间。

  • 提高线程管理的灵活性:通过线程池,开发者可以设置线程的数量、任务的队列方式,以及线程的优先级和超时时间等,从而更精细地管理并发任务。

三.线程池的使用场景:

  • 并发任务的执行:线程池广泛应用于需要同时处理多个并发任务的场景,例如 Web 服务器处理用户请求、数据处理等。
  • 定时任务:通过 ScheduledThreadPoolExecutor 执行定时或周期性任务。
  • 资源受限的场景:在线程数受限的场景中(例如有固定的 CPU 核心数或数据库连接数),线程池能够帮助限制同时执行的线程数,避免资源的过载使用。

四.使用线程池来提高Springboot项目的并发处理能力:

在 Spring Boot 项目中处理高并发时,线程池可以帮助我们管理和优化线程的使用,从而提高系统的并发处理能力。Spring Boot 提供了对线程池的内建支持,我们可以通过配置和编程方式来使用线程池。

1.在application.yml配置文件中配置:

application.yml 中,虽然 Spring Boot 默认没有直接支持线程池配置的属性,但你可以通过自定义配置类来实现线程池的配置。

spring:task:execution:pool:core-size: 10  #线程池的核心线程数max-size: 50   #线程池的最大线程数queue-capacity: 100  #线程池的任务队列容量keep-alive: 60s    #线程池中非核心线程的空闲保持时间thread-name-prefix: Async-  # 线程池中线程的名称前缀

2.定义配置类来接受配置文件内的属性值:

import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.task.TaskExecutor;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;import java.util.concurrent.Executor;@Configuration
public class TaskExecutorConfig {@Value("${spring.task.execution.pool.core-size}")private int corePoolSize;@Value("${spring.task.execution.pool.max-size}")private int maxPoolSize;@Value("${spring.task.execution.pool.queue-capacity}")private int queueCapacity;@Value("${spring.task.execution.pool.keep-alive}")private String keepAlive;@Value("${spring.task.execution.pool.thread-name-prefix}")private String threadNamePrefix;@Bean(name = "taskExecutor")public Executor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(corePoolSize);executor.setMaxPoolSize(maxPoolSize);executor.setQueueCapacity(queueCapacity);executor.setKeepAliveSeconds(Integer.parseInt(keepAlive.replace("s", ""))); // 将 "60s" 转换为 60executor.setThreadNamePrefix(threadNamePrefix);executor.initialize();return executor;}
}

3.启用异步支持:

为了确保 Spring Boot 应用程序启用了异步支持,需要在主应用类或者配置类中添加 @EnableAsync 注解:

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;@SpringBootApplication
@EnableAsync
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

4.实例:

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;@Service
public class MyService {@Async("taskExecutor")public void asyncMethod() {// 执行一些耗时操作,打印当前线程的名称System.out.println("Executing async method - " + Thread.currentThread().getName());}
}

1.@Async 注解用于将一个方法标记为异步执行。标记了 @Async 的方法会在调用时由线程池中的线程异步执行,而不是在调用线程中直接执行。

2.@Async 注解的值 "taskExecutor" 表示使用名为 taskExecutor 的线程池来执行这个异步方法。这个线程池的配置需要在 @Configuration 类中定义(如前面所述)。

 五.详细解析@Async注解的使用:

@Async 注解是 Spring 框架中用于实现异步任务执行的重要功能。它通过将任务放入线程池中执行,从而解耦了任务的执行过程和调用过程,极大地提升了系统的并发处理能力。下面我们来详细解析 @Async 注解的工作原理、配置以及与线程池的结合使用。

1.@Async注解作用:

@Async 用于将标注的方法异步执行,意思是说这个方法的执行不会阻塞调用线程。相反,Spring 会将该方法交给一个单独的线程来处理。这对于需要处理耗时任务的场景(例如,发送邮件、数据库查询、文件操作等)非常有用,能够提高系统响应能力和吞吐量。

2.@Async注解的调用过程:

当调用一个标注了 @Async 的方法时,调用者线程不会等待这个方法执行完成,而是立即返回。实际上 Spring 会将 @Async 方法提交到一个线程池中,线程池中的线程负责实际执行该方法。标注 @Async 的方法可以有返回值(异步返回 FutureCompletableFuture),也可以是 void 类型。如果不指定线程池,Spring 默认使用 SimpleAsyncTaskExecutor。但在实际项目中,通常需要自定义线程池来处理异步任务。

3.@Async注解使用:

(1)启用异步支持:

首先需要在配置类或 Spring Boot 主类中启用异步支持:

不加@EnableAsync注解,那么@Async注解不会生效。

import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.scheduling.annotation.EnableAsync;@SpringBootApplication
@EnableAsync // 启用异步任务支持
public class Application {public static void main(String[] args) {SpringApplication.run(Application.class, args);}
}

 (2)定义异步方法:

在 Spring 的服务类中,可以通过 @Async 注解来定义异步方法。方法的返回类型可以是 void,Future<T>,CompleteableFuture<T>,所以我们需要用这三种来声明返回值类型。

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;@Service
public class MyAsyncService {@Asyncpublic void asyncTask() {// 异步执行的任务System.out.println("Executing task in: " + Thread.currentThread().getName());}@Asyncpublic CompletableFuture<String> asyncTaskWithReturn() {// 异步执行的任务并返回结果System.out.println("Executing task with return in: " + Thread.currentThread().getName());return CompletableFuture.completedFuture("Task Completed");}
}

(3)调用异步方法:

异步方法会在后台线程池中执行,调用线程不会等待其执行结果:

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;@RestController
public class MyController {@Autowiredprivate MyAsyncService myAsyncService;@GetMapping("/async")public String testAsync() {// 调用异步方法myAsyncService.asyncTask();return "Task started!";}@GetMapping("/asyncReturn")public CompletableFuture<String> testAsyncWithReturn() {// 调用异步方法并获取返回结果return myAsyncService.asyncTaskWithReturn();}
}

六.CompleteableFuture返回类型的使用:

1.CompleteableFuture 是 Java 8 引入的一种用于异步编程的工具类,它是 Future 的扩展,提供了丰富的异步编程方法。CompleteableFuture 的强大之处在于其灵活性和丰富的 API,可以轻松处理异步任务的组合、链式调用、异常处理等。

2.异步方法可以返回 CompleteableFuture,以便调用方可以在合适的时机检查任务是否完成,并获取任务的结果。

@Async
public CompletableFuture<String> asyncMethodWithCompletableFuture() throws InterruptedException {Thread.sleep(1000); // 模拟耗时任务return CompletableFuture.completedFuture("Result from async task");
}

1.基本使用:

(1)通过创建 CompleteableFuture 对象来创建异步任务:

// 手动创建一个未完成的CompletableFuture对象
CompletableFuture<String> future = new CompletableFuture<>();// 使用supplyAsync创建异步任务
CompletableFuture<String> future1 = CompletableFuture.supplyAsync(() -> {return "Hello, World!";
});// 使用runAsync创建没有返回值的异步任务
CompletableFuture<Void> future2 = CompletableFuture.runAsync(() -> {System.out.println("Running a task asynchronously.");
});

(2)获取异步方法的结果:

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Result");// get() 会阻塞当前线程直到结果可用
String result = future.get();// getNow() 如果结果可用则立即返回,否则返回默认值
String resultNow = future.getNow("Default Value");// join() 类似于 get(),但不会抛出受检异常
String resultJoin = future.join();

2.链式编程:

CompletableFuture 允许你通过链式调用来构建一系列的异步任务,常用的方法有 thenApply()thenAccept()thenRun()

(1)thenApply():处理结果并返回新的值

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> 100).thenApply(result -> result * 2); // 处理结果并返回新的值

(2)thenAccept():处理结果但不返回值

CompletableFuture.supplyAsync(() -> "Hello").thenAccept(result -> System.out.println(result)); // 打印结果

(3)thenRun():完成后执行另一个操作,但不关心结果

CompletableFuture.supplyAsync(() -> "Task").thenRun(() -> System.out.println("Task completed!"));

3.组合多个异步任务进行处理:

有时我们需要同时执行多个异步任务,并在它们完成时进行进一步处理。CompletableFuture 提供了多个方法来组合任务,例如 thenCombine()thenCompose()allOf()anyOf()

(1)thenCombine() – 组合两个独立任务的结果

CompletableFuture<Integer> future1 = CompletableFuture.supplyAsync(() -> 100);
CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> 200);CompletableFuture<Integer> combinedFuture = future1.thenCombine(future2, (result1, result2) -> result1 + result2);Integer combinedResult = combinedFuture.join(); // 300

(2)thenCompose() – 链式依赖

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> "Hello").thenCompose(result -> CompletableFuture.supplyAsync(() -> result + " World"));String combinedResult = future.join(); // "Hello World"

(3)allOf() – 等待多个任务全部完成

CompletableFuture<Void> allFutures = CompletableFuture.allOf(CompletableFuture.supplyAsync(() -> "Task 1"),CompletableFuture.supplyAsync(() -> "Task 2"),CompletableFuture.supplyAsync(() -> "Task 3")
);allFutures.join(); // 等待所有任务完成

(4)anyOf() – 任意一个完成

CompletableFuture<Void> allFutures = CompletableFuture.allOf(CompletableFuture.supplyAsync(() -> "Task 1"),CompletableFuture.supplyAsync(() -> "Task 2"),CompletableFuture.supplyAsync(() -> "Task 3")
);allFutures.join(); // 等待所有任务完成

4.异常处理:

CompletableFuture 提供了几种方式来处理异常,包括 exceptionally()handle()whenComplete()。 

(1)exceptionally() – 捕获并处理异常

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {if (Math.random() > 0.5) {throw new RuntimeException("Something went wrong!");}return 100;
}).exceptionally(ex -> {System.out.println("Caught exception: " + ex.getMessage());return -1; // 返回默认值
});Integer result = future.join();

(2)handle() – 处理正常和异常情况

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {if (Math.random() > 0.5) {throw new RuntimeException("Error occurred!");}return 100;
}).handle((result, ex) -> {if (ex != null) {System.out.println("Caught exception: " + ex.getMessage());return -1; // 返回默认值}return result * 2; // 处理结果
});Integer finalResult = future.join();

(3)whenComplete() – 完成后执行处理,无论是否有异常

CompletableFuture<Integer> future = CompletableFuture.supplyAsync(() -> {if (Math.random() > 0.5) {throw new RuntimeException("Error occurred!");}return 100;
}).whenComplete((result, ex) -> {if (ex != null) {System.out.println("Task completed with exception: " + ex.getMessage());} else {System.out.println("Task completed successfully with result: " + result);}
});

5.超时处理:

CompletableFuture 还支持在异步任务中设置超时,以避免长时间等待。

(1)orTimeout() – 设置超时时间

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}return "Completed";
}).orTimeout(1, TimeUnit.SECONDS); // 超时时间为1秒future.exceptionally(ex -> {System.out.println("Task timed out");return "Timeout";
});

(2)completeOnTimeout() – 超时后返回默认值

CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}return "Completed";
}).completeOnTimeout("Default Value", 1, TimeUnit.SECONDS); // 超时返回默认值

6.细节注意:

(1)避免阻塞:

尽量避免使用 get()join() 直接阻塞主线程,尽可能使用链式操作或回调来处理异步结果。

(2)处理异常:

确保在异步操作中有良好的异常处理策略,尤其是在组合多个任务时,使用 exceptionally()handle() 捕获和处理异常。

(3)线程池优化:

默认的 CompletableFuture 使用 ForkJoinPool 来执行异步任务。对于高并发的场景,你可以通过 supplyAsync()runAsync() 的第二个参数传递自定义线程池来优化性能。


到这里,线程池的相关内容想必你已经掌握了许多了,看到这里了,记得给个三连,感谢观看!!!

相关文章:

线程池以及详解使用@Async注解异步处理方法

目录 一.什么是线程池&#xff1a; 二.使用线程池的好处&#xff1a; 三.线程池的使用场景&#xff1a; 四.使用线程池来提高Springboot项目的并发处理能力&#xff1a; 1.在application.yml配置文件中配置&#xff1a; 2.定义配置类来接受配置文件内的属性值&#xff1a…...

css鼠标移动过去变成手的图标

在css中定义 cursor:pointer;直接在html中指定 <div class"mt-2 mt-md-2 mt-lg-1 fs-md-1 fs-lg-2 " style"cursor:pointer;"></div>...

uniapp 懒加载、预加载、缓存机制深度解析

uniapp 懒加载、预加载、缓存机制深度解析 文章目录 uniapp 懒加载、预加载、缓存机制深度解析一、为什么要使用uniapp的懒加载、预加载和缓存机制二、如何使用uniapp的懒加载、预加载和缓存机制1. 懒加载2. 预加载3. 缓存机制 四、扩展与高级技巧1. 结合懒加载和预加载优化页面…...

《OpenCV计算机视觉》—— 图像形态学(腐蚀、膨胀等)

文章目录 一、图像形态学基本概念二、基本运算1.简单介绍2.代码实现 三、高级运算1.简单介绍2.代码实现 一、图像形态学基本概念 图像形态学是图像处理科学的一个独立分支&#xff0c;它基于集合论和数学形态学的理论&#xff0c;专门用于分析和处理图像中的形状和结构。图像形…...

【Rust光年纪】海洋学研究的利器:Rust语言海洋学计算库详解

探索Rust语言下的海洋学计算库&#xff1a;功能对比与选择指南 前言 随着科学技术的不断发展&#xff0c;海洋学领域对于计算和数据处理的需求也日益增长。在Rust语言中&#xff0c;出现了一系列专注于海洋学计算和数据处理的库&#xff0c;它们为海洋学工作者提供了强大的工…...

Word文档的读入【2】

现在&#xff0c;乔老师已经了解了Word文档的基本结构。 下面&#xff0c;我们通过观察一份答题卡来思考一下每条信息的具体位置。这样&#xff0c;在后面几天的学习和操作中&#xff0c;我们就能更快、更准确地读取到答题卡中的信息。 这份答题卡是由一个表格和一些段落组成。…...

报名开启 | 游戏开发缺队友?首期繁星招聘会来袭!

**点击蓝链领取游戏开发教程 ** EE GAMES 创作者社区是专注于链接每一位游戏创作者&#xff0c;提供社区交流、团队匹配、经验共享、成果展示、知识整合、最新活动资讯等全方位服务的游戏领域垂类社区。 这里不仅仅是一个游戏创作的互助平台&#xff0c;更是每一位游戏创作者…...

无法加载源https://api.nuget.org/v3/index.json的服务索引

我是用的visual studio2022 17.11.2版本&#xff0c;在运行.net c#项目的时候显示“无法加载源https://api.nuget.org/v3/index.json的服务索引”&#xff0c;从网上找了一堆方法全部没用&#xff0c;最后用这个方法解决了。亲测有效家人们 关闭VS&#xff0c;删除C:\Users\xx…...

C#--CM+Fody+HCWPF开发组合

CM&#xff1a;Caliburn.Micro(简称CM)一经推出便备受推崇&#xff0c;作为一款MVVM开发模式的经典框架&#xff0c;越来越多的受到wpf开发者的青睐.我们看一下官方的描述&#xff1a;Caliburn是一个为Xaml平台设计的小型但功能强大的框架。Micro实现了各种UI模式&#xff0c;用…...

力扣474-一和零(Java详细题解)

题目链接&#xff1a;474. 一和零 - 力扣&#xff08;LeetCode&#xff09; 前情提要&#xff1a; 因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。 最近刚学完01背包&#xff0c;所以现在的题解都是以01背包问题为基础再来写的。 如果大家不懂01背包的话&#…...

【话题】量子计算:前沿技术与应用前景深度解析

引言 在当今信息时代&#xff0c;计算能力已成为推动科技进步和社会发展的重要驱动力。随着摩尔定律逐渐接近其物理极限&#xff0c;传统计算机硬件的性能提升面临前所未有的挑战。在此背景下&#xff0c;量子计算作为一种革命性的计算范式&#xff0c;凭借其独特的量子力学属性…...

第11章 32位x86处理器编程架构

第11章 32位x86处理器编程架构 IA-32(INTEL Architecture, 32-bit)&#xff1a;INTEL 32位处理器架构简称IA-3&#xff0c;以8086处理器为基础发展起来的。该章重点介绍了IA-32处理器的工作方式和相关技术。 IA-32架构的基本执行环境 寄存器的扩展 32位处理器通用寄存器&am…...

加密软件是什么?有哪些用处呢?

一、加密软件是什么&#xff1f; 加密软件用于对数据进行加密和解密的工具或程序。其主要功能是通过使用加密算法将原始数据转换为密文&#xff0c;以保护数据的机密性和安全性&#xff0c;防止未经授权的访问和泄露。加密软件提供用户友好的界面和操作方式&#xff0c;使用户…...

浅谈C#之任务调度TaskScheduler

一、基本介绍 TaskScheduler 是一个抽象类&#xff0c;用于控制任务的执行方式&#xff0c;特别是它们如何被安排到线程池中的线程上执行。 TaskScheduler 负责将 Task 对象排队并决定何时、以何种方式执行这些任务。 二、TaskScheduler的作用 调度任务&#xff1a;将任务分配…...

SQL server 日常运维命令

一、基础命令 查看当前数据库的版本 SELECT VERSION;查看服务器部分特殊信息 select SERVERPROPERTY(Nedition) as Edition --数据版本&#xff0c;如企业版、开发版等,SERVERPROPERTY(Ncollation) as Collation --数据库字符集,SERVERPROPERTY(Nservername) as Serve…...

基于协同过滤算法+SpringBoot+Vue+MySQL的商品推荐系统

系统展示 用户前台界面 管理员后台界面 系统背景 当前的网络技术&#xff0c;软件技术等都具备成熟的理论基础&#xff0c;市场上也出现各种技术开发的软件&#xff0c;这些软件都被用于各个领域&#xff0c;包括生活和工作的领域。随着电脑和笔记本的广泛运用&#xff0c;以及…...

VSCode中latex文件(Misplaced alignment tab character .LaTeX

Misplaced alignment tab character &.LaTeX 先给出参考文章1 Misplaced alignment tab character &.LaTeX 把bib文件中的 &改为 and 。删除原有的bbl文件、重新运行 选择这个运行 这个错误在overleaf上并没有遇到、在vscode上遇到了 方法二就是把 &改为…...

如何给电脑设置静态IP地址:详细步骤与指南

在日常生活和工作中&#xff0c;我们经常需要使用电脑连接到网络。通常情况下&#xff0c;电脑会自动获取IP地址&#xff0c;但有时候&#xff0c;由于特定的网络需求或配置&#xff0c;我们可能需要手动为电脑设置静态IP地址。本文将详细介绍如何在Windows和Mac操作系统中为电…...

【Mysql】系统服务启动访问报错问题处理:this is incompatible with sql_mode=only_full_group_by

一、背景&#xff1a; 本来已经正常运行的平台&#xff0c;突然有一天由于对服务器进行部分操作迁移&#xff0c;发现jar可以正常启动&#xff0c;但是访问功能一直报错&#xff0c;监控后台日志后&#xff0c;发现了问题&#xff1a; 报错的具体信息如下&#xff1a; Caused…...

安装oh-my-zsh后报错zsh: command not found: conda问题解决

zsh: command not found: conda问题解决 一、问题介绍与环境介绍 系统为macOS Sonoma 14.5 所用终端为zsh 主要问题&#xff1a;安装了oh-my-zsh之后conda命令在终端中不可用。 二、原因分析 终端中zsh的可访问的程序一般放在/bin, /usr/bin, /usr/local/bin&#xff0c;~/bi…...

接口测试中缓存处理策略

在接口测试中&#xff0c;缓存处理策略是一个关键环节&#xff0c;直接影响测试结果的准确性和可靠性。合理的缓存处理策略能够确保测试环境的一致性&#xff0c;避免因缓存数据导致的测试偏差。以下是接口测试中常见的缓存处理策略及其详细说明&#xff1a; 一、缓存处理的核…...

多云管理“拦路虎”:深入解析网络互联、身份同步与成本可视化的技术复杂度​

一、引言&#xff1a;多云环境的技术复杂性本质​​ 企业采用多云策略已从技术选型升维至生存刚需。当业务系统分散部署在多个云平台时&#xff0c;​​基础设施的技术债呈现指数级积累​​。网络连接、身份认证、成本管理这三大核心挑战相互嵌套&#xff1a;跨云网络构建数据…...

HTML 语义化

目录 HTML 语义化HTML5 新特性HTML 语义化的好处语义化标签的使用场景最佳实践 HTML 语义化 HTML5 新特性 标准答案&#xff1a; 语义化标签&#xff1a; <header>&#xff1a;页头<nav>&#xff1a;导航<main>&#xff1a;主要内容<article>&#x…...

Golang 面试经典题:map 的 key 可以是什么类型?哪些不可以?

Golang 面试经典题&#xff1a;map 的 key 可以是什么类型&#xff1f;哪些不可以&#xff1f; 在 Golang 的面试中&#xff0c;map 类型的使用是一个常见的考点&#xff0c;其中对 key 类型的合法性 是一道常被提及的基础却很容易被忽视的问题。本文将带你深入理解 Golang 中…...

VB.net复制Ntag213卡写入UID

本示例使用的发卡器&#xff1a;https://item.taobao.com/item.htm?ftt&id615391857885 一、读取旧Ntag卡的UID和数据 Private Sub Button15_Click(sender As Object, e As EventArgs) Handles Button15.Click轻松读卡技术支持:网站:Dim i, j As IntegerDim cardidhex, …...

【Java学习笔记】Arrays类

Arrays 类 1. 导入包&#xff1a;import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序&#xff08;自然排序和定制排序&#xff09;Arrays.binarySearch()通过二分搜索法进行查找&#xff08;前提&#xff1a;数组是…...

大数据零基础学习day1之环境准备和大数据初步理解

学习大数据会使用到多台Linux服务器。 一、环境准备 1、VMware 基于VMware构建Linux虚拟机 是大数据从业者或者IT从业者的必备技能之一也是成本低廉的方案 所以VMware虚拟机方案是必须要学习的。 &#xff08;1&#xff09;设置网关 打开VMware虚拟机&#xff0c;点击编辑…...

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数

高效线程安全的单例模式:Python 中的懒加载与自定义初始化参数 在软件开发中,单例模式(Singleton Pattern)是一种常见的设计模式,确保一个类仅有一个实例,并提供一个全局访问点。在多线程环境下,实现单例模式时需要注意线程安全问题,以防止多个线程同时创建实例,导致…...

#Uniapp篇:chrome调试unapp适配

chrome调试设备----使用Android模拟机开发调试移动端页面 Chrome://inspect/#devices MuMu模拟器Edge浏览器&#xff1a;Android原生APP嵌入的H5页面元素定位 chrome://inspect/#devices uniapp单位适配 根路径下 postcss.config.js 需要装这些插件 “postcss”: “^8.5.…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...