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

多线程篇-5--线程分类(线程类型,springboot中常见线程类型,异步任务线程)

常见的线程类型包括用户线程(User Threads)、守护线程(Daemon Threads)、主线程(Main Thread)、工作线程(Worker Threads)和线程池中的线程。

一、用户线程(User Threads)

特点:

  • 用户线程是普通的Java线程,通常由程序员显式创建。
  • 用户线程在程序运行期间一直存在,直到它们完成任务或程序终止。

代码示例:

public class UserThreadExample {public static void main(String[] args) {Thread userThread = new Thread(() -> {for (int i = 0; i < 5; i++) {System.out.println("User thread running: " + i);try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});userThread.start();}
}

2、守护线程(Daemon Threads)

特点:

  • 守护线程是在后台运行的线程,它们通常用于为其他线程提供服务。
  • 当所有用户线程都结束时,JVM会自动终止守护线程并退出。(即使守护线程没有执行完任务,也会被JVM强制退出,所以主要业务一定不能放在守护线程中执行)
  • 守护线程通常用于执行一些辅助任务,如垃圾回收、日志记录等。

代码示例:

public class DaemonThreadExample {public static void main(String[] args) {Thread daemonThread = new Thread(() -> {while (true) {System.out.println("Daemon thread running...");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}}});daemonThread.setDaemon(true);  // 设置为守护线程,就这一句就够了daemonThread.start();// 主线程休眠一段时间后结束try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}}
}

解释:

  • 创建一个新的线程daemonThread,并将其设置为守护线程。
  • 守护线程无限循环运行,每秒打印一条消息。
  • 主线程休眠5秒后结束,此时JVM会自动终止,守护线程也会被终止。

3、主线程(Main Thread)

特点:

  • 主线程是每个Java应用程序的入口点,它是JVM在启动时自动创建的第一个线程。
  • 主线程负责执行main方法中的代码。
  • 当主线程结束时,如果还有其他用户线程在运行,JVM会继续运行这些线程。

代码示例:

public class MainThreadExample {public static void main(String[] args) {System.out.println("Main thread started");Thread userThread = new Thread(() -> {System.out.println("User thread running...");try {Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}});userThread.start();  // 用户线程启动,实际上就是主线程干的事情System.out.println("Main thread ending");}
}

解释:

  • 主线程执行main方法中的代码。
  • 创建并启动一个用户线程userThread。
  • 主线程在启动用户线程后继续执行打印,之后就结束了。
  • 用户线程会继续运行,直到完成任务。

4、工作线程(Worker Threads)

特点:

  • 工作线程通常用于执行具体的任务,它们可以是用户线程或守护线程。
  • 工作线程通常由线程池管理,用于处理任务队列中的任务。
  • 工作线程可以提高应用程序的并发性和性能。

代码示例:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class WorkerThreadExample {public static void main(String[] args) {ExecutorService executor = Executors.newFixedThreadPool(2);  // 创建固定大小的线程池for (int i = 0; i < 5; i++) {int taskId = i;executor.submit(() -> {System.out.println("Task " + taskId + " is running on thread " + Thread.currentThread().getName());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}});}executor.shutdown();  // 关闭线程池}
}

解释:

  • 创建一个固定大小为2的线程池executor。
  • 提交5个任务到线程池,每个任务在执行时会打印任务ID和当前线程名称。
  • 调用shutdown方法关闭线程池,等待所有任务完成。

5、线程池中的线程

特点:

  • 线程池中的线程是由线程池管理的,它们可以重复使用,减少了创建和销毁线程的开销。
  • 线程池可以控制并发线程的数量,避免过多的线程消耗系统资源。
  • 线程池通常用于处理大量的短期任务。

代码示例:

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;public class ThreadPoolExample {public static void main(String[] args) {ExecutorService executor = Executors.newCachedThreadPool();  // 创建可缓存线程池for (int i = 0; i < 10; i++) {int taskId = i;executor.submit(() -> {System.out.println("Task " + taskId + " is running on thread " + Thread.currentThread().getName());try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}});}executor.shutdown();  // 关闭线程池}
}

解释:

  • 创建一个可缓存线程池executor,它会根据需要创建新的线程。
  • 提交10个任务到线程池,每个任务在执行时会打印任务ID和当前线程名称。
  • 调用shutdown方法关闭线程池,等待所有任务完成。

6、线程分类总结

(1)、用户线程:普通的Java线程,由程序员显式创建。
(2)、守护线程:后台线程,用于提供服务,当所有用户线程结束时自动终止。
(3)、主线程:JVM自动创建的第一个线程,执行main方法中的代码。
(4)、工作线程:用于执行具体任务的线程,通常由线程池管理。
(5)、线程池中的线程:由线程池管理的线程,可以重复使用,减少开销。

7、springboot常见线程类型

(1)、主线程(Main Thread)

1、概述

  • 这是Spring Boot应用启动时由JVM创建的第一个线程。
  • 主线程负责启动Spring Boot应用,加载配置,初始化Spring容器等。

2、创建时机

  • 应用启动时,由JVM自动创建。

代码示例

@SpringBootApplication
public class MyApplication {public static void main(String[] args) {SpringApplication.run(MyApplication.class, args);}
}

(2)、Tomcat/NIO线程(接受客户端请求用)

1、概述

  • 如果你的Spring Boot应用使用了嵌入式的Tomcat服务器,Tomcat会创建多个线程来处理HTTP请求。
  • 这些线程通常是NIO线程(非阻塞线程,可异步),负责接收客户端请求并处理响应。

2、创建时机

  • 当Spring Boot应用启动并初始化嵌入式Tomcat服务器时。

配置文件示例
无需编码,仅配置即可,不配置也可以会有默认配置。

server:port: 8080tomcat:max-threads: 200  # 最大线程数min-spare-threads: 10  # 最小空闲线程数

(3)、定时任务线程(Scheduled Tasks)

1、概述

  • 如果你在Spring Boot应用中使用了定时任务(如@Scheduled注解),Spring Boot会创建一个或多个线程来执行这些定时任务。
  • 这些线程通常由TaskScheduler管理。

2、创建时机

  • 当Spring Boot应用启动并初始化定时任务时。

代码示例

@Configuration
@EnableScheduling
public class SchedulerConfig {
}@Component
public class ScheduledTasks {@Scheduled(fixedRate = 5000)   // 自动创建定时任务线程监听并执行public void performTask() {System.out.println("Executing scheduled task at " + LocalDateTime.now());}
}

(4)、异步任务线程(Async Tasks)

1、概述

  • 如果你在Spring Boot应用中使用了异步方法(如@Async注解),Spring Boot会创建一个或多个线程来执行这些异步任务。
  • 这些线程通常由TaskExecutor管理。

这个在附录中在详细说明。

(5)、自定义线程

1、概述

  • 你可以在Spring Boot应用中手动创建和管理线程,例如通过实现Runnable接口或继承Thread类。

2、创建时机

  • 在你需要的时候手动创建。

代码示例

@Component
public class CustomThreadExample {@PostConstructpublic void startCustomThread() {Thread customThread = new Thread(() -> {while (true) {System.out.println("Custom thread running at " + LocalDateTime.now());try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}}});customThread.start();}
}

附录:

异步任务线程(Async Tasks)

1、概述

  • 如果你在Spring Boot应用中使用了异步方法(如@Async注解),Spring Boot会创建一个或多个线程来执行这些异步任务,主线程不会阻塞会继续执行后面的代码。
  • 这些线程通常由TaskExecutor管理。
  • 使用异步任务,使用@EnableAsync开启后(主方法等配置入口),在需要的方法上添加@Async注解即可。
2、异步任务线程的作用
(1)、提高响应性
  • 异步任务线程可以在后台执行耗时的操作,而不阻塞主线程或请求处理线程。这样,主线程可以继续处理其他请求,提高系统的整体响应性。
(2)、优化资源利用
  • 对于耗时较长的任务,如果使用同步方式处理,可能会占用宝贵的线程资源,导致其他任务无法及时处理。异步任务线程可以将这些任务移到后台执行,释放主线程资源。
(3)、并发处理
  • 异步任务线程可以并行处理多个任务,提高系统的并发处理能力。这对于需要处理大量并发请求的应用尤其重要。
3、异步任务特点

(1)、异步任务线程:异步任务在单独的线程中执行,不会阻塞主线程。
(2)、立即返回:异步方法调用会立即返回一个CompletableFuture对象,主线程可以继续执行其他任务。
(3)、回调机制:使用thenAccept等方法注册回调函数,这些回调函数在异步任务完成时被调用(被线程池的其他线程调用),不会阻塞主线程。

4、常见的异步任务场景

(1)、邮件发送

  • 发送邮件是一个耗时操作,通常需要几秒钟甚至更长时间。使用异步任务线程可以在后台发送邮件,而不会阻塞主线程。

(2)、文件上传和下载

  • 文件上传和下载操作通常涉及大量的I/O操作,使用异步任务线程可以避免阻塞主线程,提高系统的响应性。

(3)、数据处理和计算

  • 对于复杂的数据处理和计算任务,使用异步任务线程可以将这些任务移到后台执行,释放主线程资源。

(4)日志记录

  • 日志记录操作通常需要写入磁盘,使用异步任务线程可以避免阻塞主线程,提高系统的性能。
5、异步任务线程与异步请求处理的区别

前者是优化请求响应速度,把不重要或耗时的事情放在后台慢慢执行,主线程可以继续干其他事情或直接返回的一种处理方式;后者是并行可同时接受客户端的多个请求,两者完全不是一回事,需要注意下。

(1)、异步任务线程
  • 用于处理耗时较长的后台任务。
  • 通常由开发人员手动创建和管理。
  • 使用@Async注解和TaskExecutor来实现。
    即:用于处理耗时较长的后台任务,提高系统的响应性和并发处理能力。
(2)、异步请求处理
  • 用于处理HTTP请求的异步响应。
  • 通常由Web框架(如Spring MVC,springboot)自动支持。
  • 使用CompletableFuture、DeferredResult等异步API来实现。
    即:用于处理HTTP请求的异步响应,通常由Web框架自动支持。
6、如何使用异步任务
(1)、@EnableAsync

@EnableAsync注解只需要在一个配置类上启用一次,即可在整个应用程序中启用异步任务的支持。即:开启后会告诉Spring框架扫描并管理带有@Async注解的方法。

代码示例:

import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;@Configuration
@EnableAsync
public class AsyncConfig {// 配置类可以包含其他Bean和配置
}
(2)、@Async

1、@Async注解用于标记那些需要异步执行的方法上。注意,方法必须在一个Spring管理的Bean中,否则不会扫描到。
2、@Async标记的方法将在异步任务线程中执行,不会阻塞当前线程,而是立即返回一个Future对象或CompletableFuture对象。(这个Future对象现在是无法获取结果的,只能通过定义回调的方式用于异步任务完成后再去通知调用的线程,当然如果无需等待结果的也可以直接忽略返回结果)。

(3)、异步线程池

默认情况下,Spring是使用一个简单的线程池来执行异步任务。你也可以自定义线程池注入spring容器中,以更好地控制异步任务的执行。

3.1、自定义线程池示例

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;@Configuration
@EnableAsync       // 开启异步任务
public class AsyncConfig {@Bean                      // 注入线程池public ThreadPoolTaskExecutor taskExecutor() {ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();executor.setCorePoolSize(2);executor.setMaxPoolSize(5);executor.setQueueCapacity(100);executor.setThreadNamePrefix("Async-");executor.initialize();return executor;}
}

3.2、控制器示例

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;@RestController
public class AsyncController {@Autowiredprivate AsyncService asyncService;@GetMapping("/send-email")public String sendEmail(@RequestParam String recipient, @RequestParam String message) {// 调用异步方法CompletableFuture<String> result = asyncService.sendEmail(recipient, message);// 处理异步结果result.thenAccept(response -> {   // 定义的回调方法,不会阻塞主线程,主线程会定义完成之后直接跳过该方法,往后执行。在异步任务完成后,真正执行回调方法代码的是线程池中的线程。System.out.println("Response: " + response);   // 异步任务完成后,由线程池中的线程执行,主线程不会执行。});return "Request accepted, email will be sent asynchronously";}
}

3.3、异步方法

import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import java.util.concurrent.CompletableFuture;@Service
public class AsyncService {@Asyncpublic CompletableFuture<String> sendEmail(String recipient, String message) {// 模拟耗时操作try {Thread.sleep(5000);} catch (InterruptedException e) {e.printStackTrace();}// 发送邮件System.out.println("Email sent to " + recipient + ": " + message);return CompletableFuture.completedFuture("Email sent successfully");}
}

解释一下:
1、异步方法的调用:

  • AsyncControllersendEmail方法中,调用asyncService.sendEmail方法。
  • sendEmail方法被标记为@Async,因此它会在一个异步任务线程中执行。
  • 方法调用会立即返回一个CompletableFuture<String>对象,标识异步任务的结果对象。(这个对象现在是无法获取执行结果的,因为还没有执行完成,需要想要调用线程得到响应,可以通过定义回调的方式在异步任务完成后再通知调用的线程)。
    2、处理异步结果:
  • 使用result.thenAccept(response -> { ... })方法来处理异步任务的结果。
  • thenAccept方法注册一个回调函数,当异步任务完成时,回调函数会被调用,并传入任务的结果。
  • 这个回调函数在异步任务线程中执行,不会阻塞主线程。
    3、立即返回响应:
  • AsyncControllersendEmail方法在调用异步方法后立即返回一个字符串"Request accepted, email will be sent asynchronously"
  • 这个响应告诉客户端请求已经被接受,邮件将在后台异步发送。

学海无涯苦作舟!!!

相关文章:

多线程篇-5--线程分类(线程类型,springboot中常见线程类型,异步任务线程)

常见的线程类型包括用户线程&#xff08;User Threads&#xff09;、守护线程&#xff08;Daemon Threads&#xff09;、主线程&#xff08;Main Thread&#xff09;、工作线程&#xff08;Worker Threads&#xff09;和线程池中的线程。 一、用户线程&#xff08;User Thread…...

docker快速部署gitlab

文章目录 场景部署步骤默认账号密码效果 场景 新增了一台机器, 在初始化本地开发环境&#xff0c;docker快速部署gitlab 部署步骤 编写dockerfile version: 3.7services:gitlab:image: gitlab/gitlab-ce:latestcontainer_name: gitlabrestart: alwayshostname: gitlabenviron…...

C# 数据类型详解:掌握数据类型及操作为高效编码奠定基础

本文将带你深入了解C#中各种数据类型的特点、用途和最佳实践&#xff0c;让你不仅能熟练运用基本类型&#xff0c;还能掌握如何在实际项目中做出最合适的选择。 目录 C#基本语法 C#数据类型 C#类型转换 C#变量常量 C#基本语法 在学习C#之前我们要先知道C#的基础构建是由哪些…...

burp2

声明&#xff01; 学习视频来自B站up主 **泷羽sec** 有兴趣的师傅可以关注一下&#xff0c;如涉及侵权马上删除文章&#xff0c;笔记只是方便各位师傅的学习和探讨&#xff0c;文章所提到的网站以及内容&#xff0c;只做学习交流&#xff0c;其他均与本人以及泷羽sec团队无关&a…...

[ACTF2020 新生赛]BackupFile--详细解析

信息搜集 让我们寻找源文件&#xff0c;目录扫描&#xff1a; 找到了/index.php.bak文件&#xff0c;也就是index.php的备份文件。 后缀名是.bak的文件是备份文件&#xff0c;是文件格式的扩展名。 我们访问这个路径&#xff0c;就会直接下载该备份文件。 我们把.bak后缀删掉…...

循环神经网络(RNN)简述

RNN及其变体 1、概述 (一)、概念 RNN(Recurrent Neural Network), 中文称作循环神经网络, 它一般以序列数据为输入, 通过网络内部的结构设计有效捕捉序列之间的关系特征, 一般也是以序列形式进行输出。 RNN的循环机制使模型隐层**上一时间步产生的结果, 能够作为当下时间步…...

九、Ubuntu Linux操作系统

一、Ubuntu简介 Ubuntu Linux是由南非人马克沙特尔沃思(Mark Shutteworth)创办的基于Debian Linux的操作系统&#xff0c;于2004年10月公布Ubuntu是一个以桌面应用为主的Linux发行版操作系统Ubuntu拥有庞大的社区力量&#xff0c;用户可以方便地从社区获得帮助其官方网站:http…...

SpringBoot 新冠密接者跟踪系统:校园疫情防控的智能守护者

摘 要 信息数据从传统到当代&#xff0c;是一直在变革当中&#xff0c;突如其来的互联网让传统的信息管理看到了革命性的曙光&#xff0c;因为传统信息管理从时效性&#xff0c;还是安全性&#xff0c;还是可操作性等各个方面来讲&#xff0c;遇到了互联网时代才发现能补上自古…...

【Ubuntu】E: Unable to locate package xxx

报错描述 在 Ubuntu 上 执行 apt install xxx 出现下面的报错&#xff1a; 即无法定位到该 Package&#xff0c;一般形式如下&#xff1a; # apt install xxx Reading package lists... Done Building dependency tree... Done Reading state information... Done E: Unable …...

vue多页面应用集成时权限处理问题

在多页面应用&#xff08;MPA&#xff09;中&#xff0c;权限管理通常会涉及到每个页面的访问控制、身份验证、以及权限校验。以下是几种常见的权限处理方式&#xff1a; 1. 前端路由权限控制 原理&#xff1a;虽然是多页面应用&#xff0c;通常每个页面会独立加载和渲染&…...

Socket编程(TCP/UDP详解)

前言&#xff1a;之前因为做项目和找实习没得空&#xff0c;计算机网络模块并没有写成博客&#xff0c;最近得闲了&#xff0c;把计算机网络模块博客补上。 目录 一&#xff0c;UDP编程 1&#xff09;创建套接字 2&#xff09;绑定端口号 3&#xff09;发送与接收数据 4&…...

qt QConicalGradient详解

1、概述 QConicalGradient是Qt框架中QGradient的一个子类&#xff0c;它用于创建锥形渐变效果。锥形渐变是从一个中心点出发&#xff0c;沿着360度的圆周扩散的颜色渐变。这种渐变通常用于模拟光线旋转、创建彩虹效果或实现其他复杂的颜色过渡。QConicalGradient允许你定义渐变…...

存储过程与自然语言处理逻辑的不同与结合

在现代软件开发中&#xff0c;存储过程与自然语言处理&#xff08;NLP&#xff09;逻辑都发挥着重要作用。存储过程是一种在数据库内部运行的预编译程序&#xff0c;通常用于处理与数据相关的任务&#xff0c;例如插入、更新、删除数据以及复杂的查询操作。而自然语言处理&…...

了解Linux —— 理解其中的权限

前言 在了解Linux权限之前&#xff0c;先来探讨我们使用的shell 命令它到底是什么&#xff1f; Linux 是一个操作系统&#xff0c;我们称其为内核(kernel) &#xff0c;正常情况下&#xff0c;我们一般用户操作并不是去直接使用内核&#xff0c;而是通过kernel 的外壳程序&…...

知识图谱嵌入与因果推理的结合

知识图谱通过节点&#xff08;实体&#xff09;和边&#xff08;关系&#xff09;来表示现实世界中的信息&#xff0c;但如何将这些信息转化为可进行推理和决策的形式&#xff0c;仍然是一个挑战。 另一方面&#xff0c;因果推理&#xff08;Causal Inference&#xff09;作为…...

STM32 PWM波形详细图解

目录 前言 一 PWM介绍 1.1 PWM简介 1.2 STM32F103 PWM介绍 1.3 时钟周期与占空比 二.引脚映像关系 2.1引脚映像与寄存器 2.2 复用功能映像 三. PWM 配置步骤 3.1相关原理图 3.2配置流程 3.2.1 步骤一二&#xff1a; 3.2.2 步骤三&#xff1a; 3.2.3 步骤四五六七&#xff1a; …...

Python Web 开发 FastAPI 入门:从基础架构到框架比较

Python Web 开发 FastAPI 入门&#xff1a;从基础架构到框架比较 目录 &#x1f5a5;️ Web 服务器概述&#xff08;如 Nginx、Apache&#xff09;&#x1f517; 前后端分离架构详解&#x1f504; HTTP 路由和请求处理机制&#x1f9f0; Web 框架概述&#xff1a;Django、Fla…...

基于STM32的智能仓库管理系统设计

目录 引言环境准备 硬件准备软件准备智能仓库管理系统基础 控制系统架构功能描述代码实现&#xff1a;实现智能仓库管理系统 4.1 RFID标签读取模块4.2 库存管理模块4.3 数据显示与监控模块4.4 无线通信模块应用场景&#xff1a;智能仓库管理系统优化问题解决方案与优化收尾与总…...

排序算法--堆排序【图文详解】

“留在码头的船才最安全” “但亲爱的&#xff0c;那不是造船的目的。 堆--插入heapInsert 原来有一个大根堆&#xff0c;如图&#xff1a; 现在要新插入一个数字50&#xff0c;进行插入 流程&#xff1a;和父亲相比&#xff0c;如果比父亲大&#xff0c;和父亲交换&#xff…...

FCBP 认证考试要点摘要

理论知识 数据处理与分析&#xff1a;包括数据的收集、清洗、转换、存储等基础操作&#xff0c;以及数据分析方法&#xff0c;如描述性统计分析、相关性分析、数据挖掘算法等的理解和应用 。数据可视化&#xff1a;涉及图表类型的选择与应用&#xff0c;如柱状图、折线图、饼图…...

鸿蒙生态崛起的机遇有什么

鸿蒙生态系统的崛起为各个领域带来了多个机遇&#xff0c;主要体现在以下几个方面&#xff1a; 智能设备的互联互通&#xff1a;鸿蒙系统旨在实现不同设备之间的无缝连接&#xff0c;为物联网&#xff08;IoT&#xff09;设备的发展提供了良好的基础。这将推动智能家居、智慧城…...

基础(函数、枚举)错题汇总

枚举默认从0开始&#xff0c;指定后会按顺序赋值 而这个枚举变量X&#xff0c;如果在全局&#xff08;函数外部&#xff09;定义&#xff0c;那默认为0&#xff0c;如果在函数内部&#xff08;局部变量&#xff09;&#xff0c;那就是随机值&#xff0c;必须初始化。 枚举变量…...

【Spark源码分析】规则框架- `analysis`分析阶段使用的规则

analysis分析阶段使用的规则 规则批策略规则说明SubstitutionfixedPointOptimizeUpdateFields该规则优化了 UpdateFields 表达式链&#xff0c;因此看起来更像优化规则。但是&#xff0c;在处理深嵌套模式时&#xff0c;UpdateFields 表达式树可能会非常复杂&#xff0c;导致分…...

mysql--二进制安装编译安装yum安装

二进制安装 创建用户和组 [rootlocalhost ~]# groupadd -r -g 306 mysql [rootlocalhost ~]# useradd -r -g 306 -u 306 -d /data/mysql mysql 创建文件夹并添加所属文件用户和组 [rootlocalhost ~]# mkdir -p /data/mysql [rootlocalhost ~]# chown mysql:mysql /data/mysql …...

《Django 5 By Example》阅读笔记:p339-p358

《Django 5 By Example》学习第12天&#xff0c;p339-p358总结&#xff0c;总计20页。 一、技术总结 1.项目(购物网站) django-admin startproject myshop 虽然这里只是示例&#xff0c;但我觉得这种命名为 myxxx 的习惯非常不好&#xff0c;因为在实际应用中&#xff0c;是…...

鸿蒙修饰符

文章目录 一、引言1.1 什么是修饰符1.2 修饰符在鸿蒙开发中的重要性1.3 修饰符的作用机制 二、UI装饰类修饰符2.1 Styles修饰符2.1.1 基本概念和使用场景2.1.2 使用示例2.1.3 最佳实践 2.2 Extend修饰符2.2.1 基本概念2.2.2 使用示例2.2.3 Extend vs Styles 对比2.2.4 使用建议…...

springboot359智慧草莓基地管理系统(论文+源码)_kaic

毕 业 设 计&#xff08;论 文&#xff09; 题目&#xff1a;智慧草莓基地管理系统 摘 要 现代经济快节奏发展以及不断完善升级的信息化技术&#xff0c;让传统数据信息的管理升级为软件存储&#xff0c;归纳&#xff0c;集中处理数据信息的管理方式。本智慧草莓基地管理系统就…...

单片机位数对性能会产生什么影响?!

单片机的位数是指其处理器核心的位宽&#xff0c;通常以比特&#xff08;bit&#xff09;为单位。常见的位数有8位、16位、32位和64位等。 单片机位数越高&#xff0c;处理器能够处理的数据量越大&#xff0c;性能也相应提高。 以下是对单片机位数对性能影响的详细分析&#…...

stm32内部高速晶振打开作为主时钟

首先建议你别这么干&#xff0c;因为内部晶振特别容易受温度等外界影响&#xff0c;很容易卡死或堵死程序 我是因为没画外部晶振电路&#xff0c;所以只能开内部晶振来作为时钟 适用于stm32f103系列 把下面的代码换掉源文件里的时钟源配置 /* 开启HSI 即内部晶振时钟 */RCC…...

【分页查询】.NET开源 ORM 框架 SqlSugar 系列

.NET开源 ORM 框架 SqlSugar 系列 【开篇】.NET开源 ORM 框架 SqlSugar 系列【入门必看】.NET开源 ORM 框架 SqlSugar 系列【实体配置】.NET开源 ORM 框架 SqlSugar 系列【Db First】.NET开源 ORM 框架 SqlSugar 系列【Code First】.NET开源 ORM 框架 SqlSugar 系列【数据事务…...

最新猪价格今日猪价格表/关键词排名优化江苏的团队

...

建站公司/网站查询域名

GroovyFX是一个库&#xff0c;使编写JavaFX 2.x应用程序更加简单和自然。 GroovyFX利用Groovy的Builder模式的功能来使开发人员能够以简洁的声明式风格进行编写。 以这种方式构造UI的能力使可视化正在构建的用户界面变得更加容易。 简短易懂的代码也易于维护和扩展。 GroovyFX完…...

深圳独立站建站/58精准推广点击器

1、SpringMVC 中的Interceptor 拦截请求是通过HandlerInterceptor 来实现的。在SpringMVC 中定义一个Interceptor 非常简单&#xff0c;主要有两种方式&#xff0c;第一种方式是要定义的Interceptor类要实现了Spring 的HandlerInterceptor 接口&#xff0c;或者是这个类继承实现…...

南宁做网站哪家公司好/推广的方式有哪些

弹性云服务器 ECS弹性云服务器(Elastic Cloud Server)是一种可随时自助获取、可弹性伸缩的云服务器&#xff0c;帮助用户打造可靠、安全、灵活、高效的应用环境&#xff0c;确保服务持久稳定运行&#xff0c;提升运维效率三年低至5折&#xff0c;多种配置可选了解详情用户数据注…...

可以做四级听力的网站/如何发布一个网站

2019独角兽企业重金招聘Python工程师标准>>> jQuery在1.7以后&#xff0c;添加了.one()方法。表示在元素上某个事件只能触发一次&#xff0c;并且绑定事件。 如&#xff1a; $(#id).one(click, function(){$(this).css(color,red);//改变元素样式}); 相当于&#…...

wps做网站/市场营销活动策划方案

本段代码实现了java Graphics库的最基本的功能&#xff0c;画一条直线。 import java.awt.Frame; import java.awt.Graphics; import java.awt.event.WindowAdapter; import java.awt.event.WindowEvent; import java.util.Scanner;class MyFrame extends Frame {int x1, y1, …...