C语言第18节:自定义类型——联合和枚举
1. 联合体
C语言中的联合体(Union)是一种数据结构,它允许在同一内存位置存储不同类型的数据。不同于结构体(struct),结构体的成员各自占有独立的内存空间,而联合体的所有成员共享同一块内存区域。这意味着在同一时间,联合体中只能存储一个成员的值,其他成员会被覆盖。
1.1 联合体的基本语法
联合体的声明与结构体相似,使用关键字union来定义。
编译器只为最大的成员分配足够的内存空间。联合体的特点是所有成员共用同一块内存空间。所以联合体也叫:共用体。
一个简单的联合体例子如下:
#include <stdio.h>union Data {int i;float f;char str[20];
};int main() {union Data data;data.i = 10;printf("data.i = %d\n", data.i);data.f = 220.5;printf("data.f = %.2f\n", data.f);// 注意,data.i的值会被覆盖printf("data.i = %d\n", data.i); // 这个值会发生变化return 0;
}

1.2 联合体的内存分配与大小计算
在C语言中,联合体的所有成员都共享同一块内存区域。当你定义一个联合体时,它的内存空间并不会为每个成员分配独立的内存,而是为所有成员分配一块共享的内存区域。这样,联合体的内存大小至少等于成员中最大类型的成员大小。
举个例子:
#include <stdio.h>union Data {int i; // 4 字节float f; // 4 字节char str[20]; // 20 字节
};int main() {printf("Size of union Data: %lu\n", sizeof(union Data));return 0;
}
解释:
int i通常占用 4 字节。float f通常也占用 4 字节。char str[20]占用 20 字节(每个字符占 1 字节)。
由于联合体的成员共享内存,它的大小等于其中最大成员的大小。在这个例子中,char str[20] 的大小是 20 字节,因此联合体的大小会是 20 字节。换句话说,联合体的内存分配通常是由它的最大成员决定的,且内存中只能保存一个成员的数据。
输出:
Size of union Data: 20
1.2.1 联合体的内存对齐
除了最大成员的大小外,还要注意内存对齐(memory alignment)。C语言中,对于每个数据类型,通常都有对齐要求。具体对齐方式与系统架构、编译器有关(在C语言第17节:自定义类型——结构体已经讲过了,点击链接即可查看)。内存对齐的目的是为了提高访问效率,因此编译器往往会将数据类型按一定的字节边界对齐(例如,4字节对齐、8字节对齐等)。
内存对齐的示例:
假设我们使用的是32位或64位的架构,它可能要求对齐到4字节边界。我们来观察一下一个包含不同类型成员的联合体的内存分配。
// VS2022 MSVC
#include <stdio.h>union Example {char c; // 1 字节int i; // 4 字节double d; // 8 字节
};int main() {printf("Size of union Example: %lu\n", sizeof(union Example));return 0;
}
解释:
char c占用 1 字节。int i占用 4 字节。double d占用 8 字节。
但由于内存对齐的原因,联合体的实际大小可能会比这些单独成员的大小之和要大。通常,为了提高访问速度,编译器会插入一些填充字节(padding),使得联合体的内存大小是最大对齐数的倍数。
输出:
Size of union Example: 8
为什么是8字节呢?因为联合体中最大成员是double d,它的大小是8字节,而且对齐数也是8。因此,整个联合体的大小会是8字节。
1.2.2 联合体内存分配的详细说明
- 成员共享内存:
- 联合体中的所有成员共享同一块内存区域。在任何时刻,联合体的内存中只会保存一个成员的值。
- 联合体的大小通常由最大成员的大小决定,因为它必须能够容纳最大成员的数据。
- 内存对齐:
- 编译器为了提高数据访问的效率,会根据平台的对齐要求插入填充字节(padding)。内存对齐确保数据按适当的字节边界存放(例如,4字节对齐、8字节对齐),从而使得CPU可以更快速地访问这些数据。
- 在一些平台上,数据类型可能有特定的对齐要求。
- 联合体的大小计算:
- 联合体的大小通常等于其最大成员的大小,但是,为了满足内存对齐的要求,联合体的实际大小可能会大于最大成员的大小。它会被填充到最接近对齐要求的倍数。
- 内存对齐填充通常是由编译器自动管理的,但了解这一点对于理解联合体的内存分配非常重要。
1.2.3 进一步的例子:多成员联合体与内存对齐
假设我们有一个更复杂的联合体,其中包含不同类型的数据,并且考虑到内存对齐的影响:
#include <stdio.h>union Complex {char c[21]; // 21 字节int i; // 4 字节double d; // 8 字节short s; // 2 字节
};int main() {printf("Size of union Complex: %lu\n", sizeof(union Complex));return 0;
}
分析:
char c[21]:这是一个字符数组,它占用21字节(每个字符占1字节)。没有对齐要求。int i:整数类型,通常占用4字节。要求 4 字节对齐,即它会被存储在4字节对齐的位置。double d:双精度浮点类型,通常占用8字节。要求 8 字节对齐,因此它会被存储在8字节对齐的位置。short s:短整型,通常占用2字节。要求 2 字节对齐,它会被存储在2字节对齐的位置。
联合体的实际大小
- 联合体的大小由最大对齐数决定。在这个例子中,最大成员是
double d(虽然char c[21]占用了 21 字节,但是其对齐数取决于存储的元素,即其对齐数为char的对齐数1),它的大小是 8 字节,其对齐数为 8 。因此,联合体的大小将是 8 字节的倍数。 - 即使
char c[21]占用了 21 字节,但联合体的总大小会由于对齐要求被填充到适合最大成员对齐的大小。
因此,联合体的实际大小会是 24 字节。 这是因为:
double d会占用 8 字节,并且需要 8 字节对齐,因此联合体的总大小将被填充到最接近8字节对齐的倍数,即 24 字节。
1.2.4 总结
- 联合的大小至少是最大成员的大小。
- 当最大成员大小不是最大对齐数的整数倍的时候,就要对齐到最大对齐数的整数倍。
1.3 联合体的特点
-
共享内存:联合体的所有成员共享同一块内存区域,因此一个联合变量的大小,至少是最大成员的大小。
例子:
#include <stdio.h>union Data {int i;float f;char str[20]; };int main() {union Data data;printf("&data: %p\n", &data);printf("&data.i: %p\n", &data.i);printf("&data.f: %p\n", &data.f);printf("data.str: %p\n", data.str);return 0; }
-
只能存储一个成员的值:每次只能访问联合体中的一个成员。给一个成员赋值时,其他成员的值会被覆盖。
-
节省内存空间:联合体在节省内存方面非常有用,尤其是当你需要存储多种不同类型的数据,但在任何时刻只需要其中一个类型的数据时。
例子:
#include <stdio.h> #include <string.h> union Data {int i;float f;char str[20]; };int main() {union Data data;strcpy(data.str, "abcdefgh");data.i = 0x11223344;return 0; }
| |
1.4 访问联合体成员
联合体成员可以通过.(点)操作符访问。例如:
union Data data;
data.i = 100;
printf("data.i = %d\n", data.i); // 输出100data.f = 98.6;
printf("data.f = %.2f\n", data.f); // 输出98.6
1.5 联合体的使用场景
1.5.1 场景①
在网络通信中,我们经常需要处理不同类型的数据包。这些数据包的内容可能会根据协议的不同而有所不同。例如,有些协议可能传输整数数据,有些可能传输浮动数数据,还有些可能传输字符串数据。在这种情况下,我们可以使用联合体来处理这些不同的数据格式。
场景描述:
假设你正在开发一个通信协议处理程序,该程序需要解析网络传输过来的数据包。每个数据包的类型和内容可能会有所不同,但在任何时刻,每个数据包只会包含一种类型的数据。为了节省内存,你可以使用联合体来存储不同类型的数据。
- 协议A 可能会传输一个 整数(比如用户ID)。
- 协议B 可能会传输一个 浮动数(比如温度传感器的数据)。
- 协议C 可能会传输一个 字符串(比如设备状态信息)。
通过联合体,你可以为这些数据包定义一个结构,使得它们共享同一块内存。每次你收到一个数据包时,根据协议类型,你可以决定是存储整数、浮动数,还是字符串,但内存中始终只有一种数据。
优势:
- 节省内存:由于不同数据类型共享内存,只有在需要时,才会使用最大类型的内存(例如字符串可能占用更多的字节)。
- 灵活性:能够处理不同协议的数据格式,只需要用一个联合体存储数据。
这个场景在 网络通信、嵌入式系统、文件格式解析 等领域非常常见,特别是在需要处理多种类型数据的系统中。
1.5.2 场景②
| 姓名 | 性别 | 年龄 | 婚姻状况 | 婚姻状况标记 | |||||
| 未婚 | 已婚 | 离婚 | |||||||
| 结婚日期 | 配偶姓名 | 子女数量 | 离婚日期 | 子女数量 | |||||
struct Person // 定义职工个人信息结构体类型
{char name[20]; // 姓名char sex; // 性别int age; // 年龄union MaritalState marital; // 婚姻状况int marryFlag; // 婚姻状况标记
};union MaritalState // 定义婚姻情况共用体
{int single; // 未婚struct MarriedState married; // 已婚struct DivorceState divorce; // 离婚
};struct MarriedState // 定义已婚结构体类型
{struct Date marryDay; // 结婚日期char spouseName[20]; // 配偶姓名int child; // 子女数量
};struct DivorceState // 定义离婚结构体类型
{struct Date divorceDay; // 离婚日期int child; // 子女数量
};struct Date
{int year;short month;short day;
};
1.6 联合体判断大小端
int check_sys()
{union{int i;char c;}un;un.i = 1;return un.c;//返回1是小端,返回0是大端
}
在C语言第16节:数据在内存中的存储已经讲过,这里不再赘述。
2. 枚举类型
C语言中的枚举类型(enum)是一种用户自定义的数据类型,用于表示一组具名的常量。枚举类型将一组相关的常量组合在一起,并赋予它们有意义的名字。使用枚举可以使程序的代码更加清晰、易于理解和维护。
一周的星期一到星期日是有限的7天,可以一 一列举
性别有:男、女、保密,也可以一 一列举
月份有12个月,也可以一 一列举
三原色,也是可以一 一列举
2.1 枚举类型的基本语法
定义枚举类型的语法如下:
enum 枚举名 {常量1 = 值1,常量2 = 值2,常量3 = 值3,...
};
枚举名是枚举类型的名称。常量是枚举中的各个值,通常是一些具名常量,默认情况下,枚举常量从0开始,依次递增,除非你为它们指定了不同的值。
2.1.1 例子:基本枚举类型
#include <stdio.h>enum Day {Sunday, // 默认值为 0Monday, // 默认值为 1Tuesday, // 默认值为 2Wednesday, // 默认值为 3Thursday, // 默认值为 4Friday, // 默认值为 5Saturday // 默认值为 6
};int main() {enum Day today;today = Wednesday; // today 被赋值为 3printf("Today is day number: %d\n", today); // 输出:Today is day number: 3return 0;
}
2.2 枚举常量的默认值
如果你没有为枚举常量指定值,默认情况下,第一个常量的值为 0,后续常量的值依次递增 1。例如,在上面的代码中,Sunday 默认值为 0,Monday 为 1,依此类推。
2.3 枚举常量的自定义值
你可以手动为枚举常量指定值。这意味着你可以设置任意值,而不依赖于默认的递增规则。
#include <stdio.h>enum Day {Sunday = 1, // 设定为 1Monday = 2, // 设定为 2Tuesday = 5, // 设定为 5Wednesday = 7, // 设定为 7Thursday, // 默认递增,从 8 开始Friday, // 9Saturday // 10
};int main() {enum Day today;today = Thursday; // today 被赋值为 8printf("Today is day number: %d\n", today); // 输出:Today is day number: 8return 0;
}
在这个例子中,Sunday 和 Monday 的值分别被设置为 1 和 2,而其他常量则从 Wednesday 开始自动递增。
2.4 枚举类型的实际应用
枚举常常用于表示一些固定的状态或选项,比如星期几、颜色、方向、状态码等。它能够使代码更加清晰,减少硬编码的数字。
2.4.1 例子:使用枚举表示交通信号灯的状态
#include <stdio.h>enum TrafficLight {Red, // 0Yellow, // 1Green // 2
};int main() {enum TrafficLight signal;signal = Green;if (signal == Green) {printf("Go!\n");} else if (signal == Yellow) {printf("Caution!\n");} else {printf("Stop!\n");}return 0;
}
在这个例子中,TrafficLight 枚举表示了交通信号灯的三个状态:红灯、黄灯和绿灯。每个状态有一个默认的整数值:Red 为 0,Yellow 为 1,Green 为 2。通过这种方式,代码更易理解,避免了使用数字来表示信号灯的状态。
2.5 枚举类型的大小
在 C 语言中,枚举类型的大小与编译器的实现有关。通常,编译器会根据枚举常量的取值范围来决定枚举类型的存储大小。如果枚举的值在 int 类型的范围内,编译器通常会选择 int 类型来存储枚举值。但有些编译器可能根据需要进行优化,使用较小的存储类型。
可以使用 sizeof 来查看枚举类型的大小:
#include <stdio.h>enum Color {Red = 1,Green,Blue
};int main() {printf("Size of enum Color: %lu\n", sizeof(enum Color)); // 输出枚举类型的大小return 0;
}
2.6 枚举类型的转换
枚举常量本质上是整数,因此可以将它们转换为整数类型,或者将整数值赋给枚举变量。但要注意,这种做法可能会导致不符合预期的结果。
#include <stdio.h>enum Day {Sunday = 1,Monday = 2,Tuesday = 3
};int main() {enum Day today;today = 2; // 可以将整数赋给枚举变量printf("Today is day number: %d\n", today); // 输出:Today is day number: 2return 0;
}
拿整数给枚举变量赋值在C语言中是可以的,但是在C++是不行的,C++的类型检查比较严格。
2.7 枚举的优势
- 提高代码可读性:枚举常量有具名的标识符,使代码更具语义。
- 减少硬编码数字:避免了在代码中使用没有含义的数字常量。
- 防止非法值:枚举确保变量只能取定义好的值。
- 简化调试:具名常量方便在调试时辨识。
- 增强维护性:修改枚举值时,只需要更改枚举定义,无需修改多个代码位置。
- 与
switch语句结合使用:枚举常量使得switch语句的条件判断更加清晰。 - 支持位域:与位运算结合使用,可以用来表示多个标志位。
—完—
相关文章:
C语言第18节:自定义类型——联合和枚举
1. 联合体 C语言中的联合体(Union)是一种数据结构,它允许在同一内存位置存储不同类型的数据。不同于结构体(struct),结构体的成员各自占有独立的内存空间,而联合体的所有成员共享同一块内存区域…...
C++病毒(^_^|)(2)
第二期 声明: 仅供损害电脑,不得用于非法。损坏电脑,作者一律不负责。此作为作者原创,转载请经过同意。 直接上代码 #include <bits/stdc.h> #include <windows.h> using namespace std; HHOOK g_hHook;void lrud(…...
在vscode中拉取gitee里的项目并运行
拉取项目: 方法一:vscode点击查看--->终端(或者直接通过快捷键ctrol+ `打开) 在终端内通过cd命令定位到你想存放项目的文件夹 例如:cd h: 通过命令:git clone 地址 例如:git clone newbee-mall-vue-app: 前端代码 等待拉取完成即可在对应文件夹下看到项目啦 方…...
centos7 防火墙开放指定端口
在 CentOS 7 中,默认的防火墙管理工具是 firewalld。如果你想开放一个特定的端口,以便允许外部访问,可以通过以下步骤实现: 安装 firewalld 如果你的系统上还没有安装 firewalld,你可以通过以下命令安装: …...
Day42(补)【AI思考】-编译过程中语法分析及递归子程序分析法的系统性解析
文章目录 编译过程中语法分析及递归子程序分析法的系统性解析**一、总览:编译流程中的语法分析****1. 编译过程核心步骤** **二、语法分析的核心任务****1. 核心目标****2. 现实类比** **三、递归子程序分析法的本质****1. 方法分类****2. 递归子程序分析法的运作原…...
AI成为基础设施有哪些研究方向:模型的性能、可解释性,算法偏见
AI成为基础设施有哪些研究方向 模型的性能、可解释性和降低训练成本 伦理问题:算法偏见、数据隐私保护、人工智能的权利和责任 数据使用问题:公开数据已经使用完了,未来使用隐私数据(专家) 当AI成为基础设施后,研究方向将更加多元化和深入,涵盖技术创新、应用拓展、…...
写一个鼠标拖尾特效
思路和逻辑 要实现鼠标拖尾特效,我们需要: 监听鼠标移动事件,获取鼠标的当前位置。在每次鼠标移动时,绘制一个小圆点或其他形状在鼠标的当前位置。将所有绘制的圆点连接起来,形成一条“尾巴”。使用动画效果让尾巴看…...
Redisson介绍和入门使用
一、什么是Redisson? Redisson是一个在Redis的基础上实现的Java驻内存数据网格(In-Memory Data Grid)。它不仅提供了一系列的分布式的Java常用对象,还提供了许多分布式服务,其中就包含了各种分布式锁的实现。 官网地址…...
OpenAI推出全新AI助手“Operator”:让人工智能帮你做事的新时代!
引言 随着人工智能技术的不断发展,OpenAI 再次推出令人兴奋的功能——Operator,一个全新的 AI 助手平台。这不仅仅是一个普通的助手,它代表了人工智能技术的又一次飞跃,将改变我们工作和生活的方式。 什么是“Operator”ÿ…...
Python----PyQt开发(PyQt基础,环境搭建,Pycharm中PyQttools工具配置,第一个PyQt程序)
一、QT与PyQT的概念和特点 1.1、QT QT是一个1991年由The Qt Company开发的跨平台C图形用户界面应用程序开发 框架,可构建高性能的桌面、移动及Web应用程序。也可用于开发非GUI程序,比如 控制台工具和服务器。Qt是面向对象的框架,使用特殊的代…...
算法笔记 02 —— 入门模拟
本系列为胡凡编著的算法笔记当中代码部分的精简版整理,笔者也在同时准备Leetcode刷题和实习面试,希望为有一定编码和数据结构基础的同学提供一份系统型的参考,以方便遗忘时的算法查阅、期末复习总览以及C学习参照。 目录 01 简单模拟 Ⅰ害…...
PyTorch 源码学习:从 Tensor 到 Storage
分享自己在学习 PyTorch 源码时阅读过的资料。本文重点关注 PyTorch 的核心数据结构 Tensor 的设计与实现。因为 PyTorch 不同版本的源码实现有所不同,所以笔者在整理资料时尽可能按版本号升序,版本号见标题前[]。最新版本的源码实现还请查看 PyTorch 仓…...
uniapp 使用 鸿蒙开源字体
uniapp vue3 使用 鸿蒙开源字体 我的需求是全局使用鸿蒙字体。 所以: 0. 首先下载鸿蒙字体: 鸿蒙资源 下载后解压,发现里面有几个文件夹: 字体名称说明Sans默认的鸿蒙字体,支持基本的多语言字符(包括字…...
LabVIEW多电机CANopen同步
核心问题与解决方案 通信层配置 节点ID与波特率冲突问题:在多电机系统中,节点ID重复或波特率不匹配常导致通信中断或数据丢失。案例:某3轴贴片机因步科驱动器的默认节点ID均为1,触发了总线仲裁错误。解决方案:通过配置…...
每日定投40刀BTC(2)20250209 - 20250212
行路吟 青山叠叠水迢迢, 步履虽艰志未消。 莫问前程几多苦, 长风破浪自逍遥。...
【LeetCode Hot100 子串】和为 k 的子数组、滑动窗口最大值、最小覆盖子串
子串 1. 和为 k 的子数组题目描述解题思路主要思路步骤 时间复杂度与空间复杂度代码实现 2. 滑动窗口最大值题目描述解题思路双端队列的原理:优化步骤: Java实现 3. 最小覆盖子串题目描述解题思路滑动窗口的基本思路:具体步骤:算法…...
某虚拟页式存储管理系统中有一个程序占8个页面,运行时访问页面的顺序是1,2,3,4,5,3,4,1,6,7,8,7,8,5。假设刚开始内存没有预装入任何页面。
某虚拟页式存储管理系统中有一个程序占8个页面,运行时访问页面的顺序是1,2,3,4,5,3,4,1,6,7,8,7,8,5。假设刚开始内存没有预装入任何页面。 (1) 如果采用LRU调度算法,该程序在得到4块内存空间时,会产生多少次缺页中断?请给出详细…...
傅里叶公式推导(三)
文章目录 周期 2L周期T 周期 2L 周期 T 2 L T2L T2L 的傅里叶变换 即 f ( t ) f ( t 2 L ) f(t) f(t2L) f(t)f(t2L) xt2 π \pi π 2 L 2L 2L 原公式 f ( x ) a 0 2 ∑ n 1 ∞ [ a n cos n x b n sin n x ] a 0 1 π ∫ − π π f ( x ) d x a n 1 π ∫…...
Ubuntu 下 nginx-1.24.0 源码分析 - ngx_time_update函数
定义在 src\core\ngx_times.c 中 ngx_time_init 函数后面 void ngx_time_update(void) {u_char *p0, *p1, *p2, *p3, *p4;ngx_tm_t tm, gmt;time_t sec;ngx_uint_t msec;ngx_time_t *tp;struct timeval tv;if (!ngx_trylock(&ngx…...
老牌系统工具箱,现在还能打!
今天给大家分享一款超实用的电脑软硬件检测工具,虽然它是一款比较“资深”的软件,但依然非常好用,完全能满足我们的日常需求。 电脑软硬件维护检测工具 功能强大易用 这款软件非常贴心,完全不需要安装,直接打开就能用…...
铭豹扩展坞 USB转网口 突然无法识别解决方法
当 USB 转网口扩展坞在一台笔记本上无法识别,但在其他电脑上正常工作时,问题通常出在笔记本自身或其与扩展坞的兼容性上。以下是系统化的定位思路和排查步骤,帮助你快速找到故障原因: 背景: 一个M-pard(铭豹)扩展坞的网卡突然无法识别了,扩展出来的三个USB接口正常。…...
大学生职业发展与就业创业指导教学评价
这里是引用 作为软工2203/2204班的学生,我们非常感谢您在《大学生职业发展与就业创业指导》课程中的悉心教导。这门课程对我们即将面临实习和就业的工科学生来说至关重要,而您认真负责的教学态度,让课程的每一部分都充满了实用价值。 尤其让我…...
安卓基础(aar)
重新设置java21的环境,临时设置 $env:JAVA_HOME "D:\Android Studio\jbr" 查看当前环境变量 JAVA_HOME 的值 echo $env:JAVA_HOME 构建ARR文件 ./gradlew :private-lib:assembleRelease 目录是这样的: MyApp/ ├── app/ …...
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 开发者设计的强大库ÿ…...
三分算法与DeepSeek辅助证明是单峰函数
前置 单峰函数有唯一的最大值,最大值左侧的数值严格单调递增,最大值右侧的数值严格单调递减。 单谷函数有唯一的最小值,最小值左侧的数值严格单调递减,最小值右侧的数值严格单调递增。 三分的本质 三分和二分一样都是通过不断缩…...
AI语音助手的Python实现
引言 语音助手(如小爱同学、Siri)通过语音识别、自然语言处理(NLP)和语音合成技术,为用户提供直观、高效的交互体验。随着人工智能的普及,Python开发者可以利用开源库和AI模型,快速构建自定义语音助手。本文由浅入深,详细介绍如何使用Python开发AI语音助手,涵盖基础功…...
【Kafka】Kafka从入门到实战:构建高吞吐量分布式消息系统
Kafka从入门到实战:构建高吞吐量分布式消息系统 一、Kafka概述 Apache Kafka是一个分布式流处理平台,最初由LinkedIn开发,后成为Apache顶级项目。它被设计用于高吞吐量、低延迟的消息处理,能够处理来自多个生产者的海量数据,并将这些数据实时传递给消费者。 Kafka核心特…...
Qt的学习(一)
1.什么是Qt Qt特指用来进行桌面应用开发(电脑上写的程序)涉及到的一套技术Qt无法开发网页前端,也不能开发移动应用。 客户端开发的重要任务:编写和用户交互的界面。一般来说和用户交互的界面,有两种典型风格&…...
Java并发编程实战 Day 11:并发设计模式
【Java并发编程实战 Day 11】并发设计模式 开篇 这是"Java并发编程实战"系列的第11天,今天我们聚焦于并发设计模式。并发设计模式是解决多线程环境下常见问题的经典解决方案,它们不仅提供了优雅的设计思路,还能显著提升系统的性能…...
Java多线程实现之Runnable接口深度解析
Java多线程实现之Runnable接口深度解析 一、Runnable接口概述1.1 接口定义1.2 与Thread类的关系1.3 使用Runnable接口的优势 二、Runnable接口的基本实现方式2.1 传统方式实现Runnable接口2.2 使用匿名内部类实现Runnable接口2.3 使用Lambda表达式实现Runnable接口 三、Runnabl…...
