智能化建设网站深圳网站建设公司 概况

bicheng/2026/1/22 1:05:15/文章来源:
智能化建设网站,深圳网站建设公司 概况,uc浏览器网页版打开,做网站前台模板目录 前言#xff1a; 一、什么是线程 #xff08;一#xff09;基本概念 #xff08;二#xff09;线程理解 #xff08;三#xff09;线程与进程的关系 #xff08;四#xff09;简单实用线程 #xff08;五#xff09;重谈虚拟地址空间 1. 页表的大小 2…目录 前言 一、什么是线程 一基本概念 二线程理解 三线程与进程的关系 四简单实用线程 五重谈虚拟地址空间 1. 页表的大小 2. 内存与磁盘的交互 3. 局部性原理 4. 页表映射原理 5. 扩展动态内存管理 六小结 二、线程优缺点 一优点 二缺点 三线程用途 前言 将一份代码成功编译后可以得到一个可执行程序程序运行后操作系统会生成对应数据结构比如 PCB对其进行管理及分配资源并且相关代码和数据被 加载 到内存中准备工作做完之后我们就可以得到一个运行中的程序简称为 进程。对于操作系统来说光有 进程 的概念是无法满足高效运行的需求的因此需要一种执行粒度更细、调度成本更低的执行流而这就是线程。 Windows11中的线程 一、什么是线程 一基本概念 教材观点 线程就是一个执行分支、执行粒度比进程更细、调度成本更低线程就是进程内部的一个执行流 内核观点 进程是承担系统资源分配的基本实体而线程是 CPU 调度的基本单位 线程是对以往进程概念的补充完善正确理解线程概念是一件十分重要的事。 二线程理解 注意以下理解是站在 Linux 系统的角度对于线程的理解不同的操作系统具体实现方式略有差异。 理解 线程 之前需要先简单回顾一下 进程 程序运行后操作系统为其创建对应的 PCB 数据结构然后生成虚拟地址空间、分配内存资源相关的代码和数据会被 load 到内存中并通过页表建立映射关系。 进程之间是相互独立的 即使是 父子进程他们也有各自的 虚拟地址空间、映射关系、代码和数据可能共享部分数据出现修改行为时引发 写时拷贝机制 如果我们想要创建 其他进程 执行任务那么 虚拟地址空间、映射关系、代码和数据 这几样东西是必不可少的想象一下如果只有进程的概念并且同时存在几百个进程那么操作系统调度就会变得十分臃肿。 操作系统在调度进程时需要频繁保存上下文数据、创建的虚拟地址空间及建立映射关系 为了避免这种繁琐的操作引入了 线程 的概念所谓线程就是额外创建一个 task_struct 结构该 task_struct 同样指向当前的虚拟地址空间并且不需要建立映射关系及加载代码和数据如此一来我们就会发现我们新创建的task_struct 好像也是一个进程更是一个独立的执行流其实这就是创建一个线程。操作系统只需要针对一个 task_struct 结构即可完成调度成本非常低。 为什么线程其执行粒度比进程更细 现在一个进程有多个task_struct 都指向同一个地址空间。把地址空间中例如代码区的代码划分成多个部分每一个 task_struct 在未来执行时都执行同一个地址空间的不同部分的代码。这样一个进程中就存在了多个执行流(线程)。因此线程是一个执行分支这样每个线程就能更精确的执行完成任务。 为什么调度线程的成本比进程更低 在 CPU 内部包括运算器、控制器、寄存器、MMU、硬件级缓存cache其中 硬件级缓存 cache 又称为 高速缓存遵循计算机设计的基本原则局部性原理会预先加载 部分用户可能访问的数据并在接下来的执行中有很大的概率命中这些数据从而提高整机的效率。如果需要切换进程会导致 高速缓存 中的数据无法使用进程具有独立性需重新开始 预加载这是非常浪费时间的对于 CPU 来说但切换线程就不一样了由于进程没变所以缓存内容也不变切换线程时所需要的数据的也不会发生改变这就意味值 高数缓存 中的数据可以继续使用不需重新加载并且可以接着 预加载 下一波数据。 注高速缓存中预加载的是公共数据并非线程的私有数据 进程process的 task_struct 称为 PCB线程thread的 task_struct 则称为 TCB 从今天开始无论是 进程 还是 线程都可以称为 执行流线程 从属于 进程当进程中只有一个线程时我们可以粗粒度的称当前进程为一个单独的执行流当进程中有多个线程时则称当前进程为多执行流其中每一个执行流就是一个个的线程。 执行流的调度由操作系统负责CPU 只负责根据 task_struct 结构进行计算 若下一个待调度的执行流为一个单独的进程操作系统仍需创建 PCB 及 虚拟地址空间、建立映射关系、加载代码和数据。但如果下一个待调度的执行流为一个线程操作系统只需要创建一个 TCB并将其指向已有的虚拟地址空间即可。 三线程与进程的关系 进程是承担系统资源分配的实体比如 程序运行必备的虚拟地址空间、页表映射关系、相关数据和代码 这些都是存储在 进程 中的也就是我们历史学习中 进程 的基本概念。 线程是 CPU 运行的基本单位程序运行时CPU 只认识 task_struct 结构并不关心你是线程还是进程不过线程包含于进程中一个 进程可以只有一个线程也可以有很多线程当只有一个 线程时通常将其称为 进程但对于CPU 来说这个进程本质上仍然是线程因为 CPU 只认 task_struct 结构并且 PCB 与 TCB 都属于 task_struct 所以才说线程是CPU 运行的基本单位。 总结进程是由操作系统将程序运行所需地址空间、映射关系、代码和数据打包后的资源包而 线程/轻量级线程/执行流 则是利用资源完成任务的基本单位。 我们之前学习的进程概念是不完整的引入线程之后可以对进程有一个更加全面的认识。 通常将程序启动比如 main 函数中的这个线程称为 主线程其他线程则称为 次线程 实际上 进程  PCB  TCB  虚拟地址空间 映射关系 代码和数据这才是一个完整的概念 以后谈及进程时就要想到 一批执行流可支配的资源 在 Linux 中认为 PCB 与 TCB 的共同点太多了于是直接复用了 PCB 的设计思想和调度策略在进行 线程管理 时完全可以复用 进程管理 的解决方案代码和结构这可以大大减少系统调度时的开销做到 小而美因此 Linux 中实际是没有真正的 线程 概念的有的只是复用 PCB 设计思想的 TCB。在这种设计思想下线程 注定不会过于庞大因此 Linux 中的 线程 又可以称为 轻量级进程LWP轻量级进程 足够简单且 易于维护、效率更高、安全性更强可以使得 Linux 系统不间断的运行程序不会轻易 崩溃。 与 一切皆文件一样这种设计思想注定 Linux 会成为一款 卓越 的操作系统 别的系统采用的是其他方案比如 Windows 使用的是真线程方案为 TCB 额外设计了一逻辑这就导致操作系统在同时面临 PCB 和 TCB 时需要进行识别后切换成不同的处理手段存在不同的逻辑容易增加系统运行不稳定的风险这就导致 Windows 无法做到长时间运行需要通过重启来重置风险 此时我的电脑中同时存在几百个进程和几千个真线程可想而知操作系统的负担有多大 四简单实用线程 接下来简单使用一下 pthread 线程原生库中的线程相关函数只是简单使用不涉及其他操作 #include iostream #include unistd.h #include pthread.husing namespace std;void *threadHandler1(void *args) {while (true){cout 我是次线程1我正在运行... endl;sleep(1);} }void *threadHandler2(void *args) {while (true){cout 我是次线程2我正在运行... endl;sleep(1);} }void *threadHandler3(void *args) {while (true){cout 我是次线程3我正在运行... endl;sleep(1);} }int main() {pthread_t t1, t2, t3; // 创建三个线程pthread_create(t1, NULL, threadHandler1, NULL);pthread_create(t2, NULL, threadHandler2, NULL);pthread_create(t3, NULL, threadHandler3, NULL);// 主线程运行while (true){cout 我是主线程 endl;sleep(1);}return 0; }编译程序时需要带上 -lpthread 指明使用 线程原生库 g -o $ $^ -stdc11 -lpthread结果主线程三个次线程同时在运行 至于为什么打印结果会有点不符合预期这就涉及到 加锁 相关问题了后面再解决 使用指令查看当前系统中正在运行的 线程 信息 ps -aL | head -1 ps -aL | grep mythread | grep -v grep可以看到此时有 四个线程 细节1四个线程的 PID 都是 24786细节2四个线程的 LWP 各不相同细节3第一个线程的 PID 和 LWP 是一样的 其中第一个线程就是 主线程也就是我们之前一直很熟悉的 进程因为它的 PID 和 LWP 是一样的所以只需要关心 PID 也行。 操作系统如何判断调度时是切换为 线程 还是切换为 进程  将待切换的执行流 PID 与当前执行流的 PID 进行比对如果相同说明接下来要切换的是 线程否则切换的就是 进程。操作系统只需要找到 LWP 与 PID 相同的线程即可轻松锁定主线程。 线程是进程的一部分给其中任何一个线程发送信号都会影响到其他线程进而影响到整个进程。 五重谈虚拟地址空间 注当前部分是拓展与线程没有很大的关系但是一个比较重要的知识点 1. 页表的大小 页表 是用来将 虚拟地址 和 物理地址 之间建立映射关系的页表难道真的只是简单一 一存储映射吗除此之外页表 中还存在 其他属性 字段 在 32 位系统中存在 2^32 个地址一个内存单元大小是 1byte虚拟地址空间中的每一个地址依次为 [0, 2^32 − 1] 即 0x00000000 - 0xFFFFFFFF也就是我们常说的 4 GB 虚拟内存空间。 假设极端情况每个地址都在页表中建立了映射关系其中页表的每一列大小都是 4 字节那么页表的大小就是 2^32 * 4 * 3 * 1byte  48GB这就意味着悲观情况下页表已经干掉 48GB 的内存了但现在电脑普遍都只有 16GB 内存更何况是几十年前的电脑。 所以说页表绝对不是采用这种单纯 地址-地址 的映射方案。 2. 内存与磁盘的交互 操作系统从 磁盘 中读取数据时一次读取大量数据 比 多次读取少量数据 要快的多因为 磁盘 是外设每一次读取都必然伴随着寻址等机械运动机械硬盘无论是对于 内存 还是 CPU 这都是非常慢的为了尽可能提高效率操作系统选择一次 IO 大量数据的方式读取数据。 通常 IO 的数据以 块 为基本单位在文件系统中一个 块 的大小为 4KB一个块由8个扇区组成单个扇区大小为 512Byte所以OS在和磁盘这样的设备进行IO交互的时候就不能按照字节为单位的而是要按照块为单位。即使我们一次只想获取一个字节操作系统最低也会 IO 一个 数据块4KB。 4KB 这个大小很关键 文件系统/编译器文件存储时需要以 4KB 为单位进行存储操作系统/内存读取文件或进行内存管理时也是以 4KB 为单位的 为了让内存与与磁盘更高效地进行IO操作系统对内存也进行了按管理划分OS将内存划分成一个个页框其中每个页框可以存储的数据的大小为4KB这4KB被称为页 (Page)的数据。 为了将内存中的 页 Page 进行管理需要 先描述在组织构建 struct page 结构体用于描述 页 Page 的各种属性比如是否为脏数据、是否已经被占用了因为存在很多 页 Page所以需要将这些 struct page 结构进行管理使用的就是 数组(天然有下标) struct page mem[N]其中 N 表示当前内存中的 页 Page 数量。 struct page {int status; // 基础字段状态// 注意这个结构不能设计的太复杂了因为稍微大一点内存就爆了所以里面的属性非常少 };struct page mem[N]; // 管理 page 结构体的数组假设我们的内存为 4GB那么等分为 4KB 的 页 Page可以得到约 100w 个 页 Page其中 struct page 结构体不会设计的很大大小是 字节 级别的也就是说 struct page mem[100w] 占用的总大小不过 4~5MB对于偌大的内存来说可以忽略不计。 内存管理的本质 申请无非就是寻找 mem 数组中一块未被使用的足量空间将对应的 页 Page 属性设置为已被申请并返回起始地址足量空间页框的起始地址。使用将磁盘中的指定的 4KB 大小数据块存储至内存中对应的 页 Page 中。释放将 页 Page 属性设置为可用状态。 3. 局部性原理 重新视 4KB为什么内存与磁盘交互的基本单位是 块4KB 这里就要提一下 局部性原理 了 局部性原理的特征 现代计算机预加载的理论基础允许我们提前加载正在访问数据的 相邻或者附加的数据数据预加载 局部性原理 的核心在于 预加载如果没有 局部性原理那么我们可能今天都用不上电脑因为如果没有这个原则那么内存在于磁盘交互时只能做到用户需要什么就申请什么这会直接拉低 CPU 的速度而速度极快的 磁盘 又非常贵。 而 局部性原理 有效避免了这个问题用户访问数据时操作系统不仅会加载用想要访问的数据同时还会加载当前数据的临近数据如此一来就可以做到用户访问下一份数据时不必再次 IO尽量减少 IO 的次数。 合理性用户访问的数据大多都是具有一定连续性的比如用户访问 668 号数据那么他下一次想访问的数据大概是 669 及以后因此可以提前加载669及以后的数据。 配合上 4KB 的块大小可以使得每次 IO 足量的数据并且有可能会多出起到 预加载 的效果 所以现在就可以回答为什么是 4KB  IO 的基本单位内核系统/文件系统 都对其提供了支持利于通过 局部性原理 预测数据的命中情况尽可能提高效率 总结IO 的基本单位是 4KB 内存实际上被划分成了很多个 4KB 的小块并存在相应的数据结构对其进行管理。 4. 页表映射原理 显然页表 绝对不可能动辄几十个 GB实际在根据 虚拟地址 进行寻址时页表 也有自己的设计逻辑。 虚拟地址32 位操作系统 大小也就是 32 比特位大概也就是 4Byte通常将一个 虚拟地址 分割为三份10、10、12 10虚拟地址中的前 10 个比特位用于寻址 页表210虚拟地址中间的 10 个比特位用于寻找 页框起始地址12虚拟地址中的后 12 个比特位用于定位 具体地址偏移量 所以实际上在通过 页表 进行寻址时需要用到 两个页表为了方便演示仅包含一组 kv 关系 注“页表2” 中的 20 表示内存中的下标即 页框地址 通常将 “页表1” 称为 页目录“页表2” 称为 页表项 页目录使用 10 个比特位定位 页表项页表项使用 10 个比特位定位 页框地址偏移量使用 12 个比特位在 页 Page 中进行任意地址的寻址 所以即使是每个 物理地址 都被寻址的的极端情况下页表 总大小不过为(2^10 2^10) * (2^10 2^20)大约也就需要 4Mb 大小即可映射至每一个 物理内存但实际上 物理内存 并不会被时刻占满大多数情况下都是使用一部分因此实际页表大小不过 几十字节。 像这种 页框起始地址偏移量 的方式称为 基地址偏移量是一种运用十分广泛的思想比如所谓的 类型int、double、char…都是通过 类型的起始地址类型的大小 来标识该变量大小的也就是说我们只需要 获得变量的起始地址即可自由进行偏移操作如果偏移过度了就是越界这也就解释了为什么取地址只会取到 起始地址。 总结得益于 划分偏移 的思想使得页表的大小可以变得很小。 5. 扩展动态内存管理 实际上我们在进行 动态内存管理malloc/new 申请堆空间时操作系统 并没有立即在物理内存中申请空间因为你申请了可能不会立马使用而是 先在 虚拟地址 中进行申请成本很低当我们实际使用该空间时操作系统 再去 填充相应的页表信息申请具体的物理内存。 像这种操作系统赌博式的行为我们已经不是第一次见了比如之前的 写时拷贝就是在赌你不会修改这样做的好处就是可以 最大化提高效率对于内存来说这种使用时再申请的行为会引发 缺页中断。 具体原理  当用户 动态申请内存 时操作系统只会在虚拟地址中申请具体表现为 返回一块未被使用的空间起始地址用户实际使用这块空间时遵循 查页表、寻址物理内存 的原则实际进行 查页表 操作时发现 页表项 没有记录此地址的映射关系于是就会引发 缺页中断发出对应的 中断信号陷入内核态通过 中断控制器 识别 中断信号 后做出相应的动作比如这里的动作是填充页表信息、申请物理内存 把 物理内存 准备好后用户就可以进行正常使用了整个过程非常快对于用户来说几乎无感知。 同理在进行 磁盘文件读取 时也存在 缺页中断 行为毕竟你打开文件了并不是立即进行读写操作的。 诸如这种 硬件级的中断行为 我们已经在 以往 信号产生 章节 中学过了即从键盘按下的那一刻发出硬件中断信号中断控制器识别为 键盘 发出的信号后去 中断向量表 中查找执行方法也就是 键盘 的读取方法。 所以操作系统根本不需要关系 硬件 是什么样子只需要关心对方是否发出了 信号请求并作出相应的 动作执行方法 即可很好的实现了 解耦。 对于 内存 的具体情况诸如是否命中、是否被占用、对应的 RWX 权限 需要额外的空间对其进行描述而 页表 中的 其他属性 列就包含了这些信息 对 内存 进行操作时势必要进行 虚拟地址到物理地址 之间的转换而 MMU 机制 页表信息 可以判断 当前操作 是否合法如果不合法会报错。 注UK 权限用于区分当前是用户级页表还是内核级页表 比如这段代码 char *ps good morning; *ps A; // 此时程序会报错需要赋值为字符否则无法编译结合 页表、信号 等知识解释整个报错逻辑 good morning 属于字符常量存储在字符常量区中其中的权限为 R。char *ps 属于一个指针变量指向字符常量的起始地址当我们进行 *ps A 操作时首先会将字符常量的地址转换为物理地址在转换过程中MMU 机制发现该内存权限仅为 R但 *ps 操作需要 W 权限于是 MMU 引发异常 - 操作系统识别到异常将该异常转换为 信号 - 并把 信号 发给出现问题的 进程 - 信号暂时被保存 - 在 内核态转为用户态 的过程中进行 信号处理 - 最终结果是终止进程也就是报错。 程序运行后就会报错 六小结 所以目前 地址空间 的所有组成部分我们都已经打通了再次回顾这种设计时会发现 用户压根不知道、也不需要知道虚拟地址空间之后发生的事只需要正常使用就好了当引发异常操作时操作系统能在 查页表 阶段就进行拦截而不是等到真正影响到 物理内存 时才报错。 所谓的 虚拟地址空间 就是在进行设计时添加的一层 软件层它解决了 多进程时的物理内存访问问题、也解决了物理内存的保护问题同时还为用户提供了一个简单的虚拟地址空间做到了 虚拟与物理 的 完美解耦 这种设计思想就是计算机界著名的 所有问题都可以通过添加一层 软件层 解决这种思想早在几十年前就已经得到了运用。 这种分层结构不仅适用于 操作系统还适用于 网络比如大名鼎鼎的 OSI 七层网络模型。 二、线程优缺点 Linux 中没有 真线程有的只是复刻进程代码和管理逻辑的 轻量级线程LWP 线程 有以下概念 在一个程序中的一个执行路线就叫做 线程Thread或者说 线程 是一个进程内部的控制程序每一个进程都至少包含一个 主线程线程 在进程内部执行本质上仍然是在进程地址空间内运行在 Linux 系统中CPU 看到的 线程TCB 比传统的 进程PCB 更加轻量化透过进程地址空间可以看到进程的大部分资源将资源合理分配给每个执行流就形成了 线程执行流 一优点 线程 最大的优点就是 轻巧、灵活更容易进行调度 创建一个线程的代价比创建一个进程的代价要小得多调度线程比调度进程要容易得多线程占用的系统资源远小于进程可以充分利用多处理器的并行数量进程也可以在等待慢速 IO 操作时程序可以执行其他任务比如看剧软件中的 “边下边看” 功能对于计算密集型应用可以将计算分解到多个线程中实现比如 压缩/解压 时涉及大量计算对于 IO密集型应用为了提高性能将 IO操作重叠线程可以同时等待资源进行 高效IO比如 文件/网络 的大量 IO 需要可以通过 多路转接 技术提高效率 线程 的合理使用可以提高效率但 线程不是越多越好而是 合适 最好让每一个线程都能参与到计算中。 二缺点 线程 也是有缺点的1、性能损失当线程数量过多时频繁的线程调度所造成的消耗会导致 计算密集型应用 无法专心计算从而造成性能损失。 2、 健壮性降低在一个多线程程序里因时间分配上的细微偏差或者因共享了不该共享的变量而造成不良影响的可能性是很大的换句话说线程之间是缺乏保护的。 在下面这个程序中次线程4 出现异常后会导致整个进程运行异常进而终止进程 #include iostream #include unistd.h #include pthread.husing namespace std;void *threadHandler1(void *args) {while (true){cout 我是次线程1我正在运行... endl;sleep(1);} }void *threadHandler4(void *args) {while (true){sleep(5); // 等其他线程先跑一会cout 我是次线程4我正在运行... endl;char *ps good morning;*ps A;} }int main() {pthread_t t1, t4; // 创建两个线程pthread_create(t1, NULL, threadHandler1, NULL);pthread_create(t4, NULL, threadHandler4, NULL);// 主线程运行while (true){cout 我是主线程 endl;sleep(1);}return 0; }结果一轮到次线程4运行因为触发异常从而整个进程就直接终止了  为什么 单个线程 引发的错误需要让 整个进程 来承担 站在技术角度完全可以让其自行承担但这不合理系统角度线程是进程的执行分支线程出问题了进程也不应该继续运行比如一颗老鼠屎坏了一锅汤信号角度线程出现异常后MMU 识别到异常 - 操作系统将异常转换为信号 - 发送信号给指定 3、缺乏访问控制进程是访问控制的基本粒度在一个线程中调用某些OS函数会对整个进程造成影响 #include iostream #include unistd.h #include pthread.husing namespace std;int g_val 0;void *threadHandler1(void *args) {while (true){printf(我是次线程1我正在运行... g_val: %p g_val: %d\n, g_val, g_val);sleep(1);} }void *threadHandler2(void *args) {while (true){printf(我是次线程2我正在运行... g_val: %p g_val: %d\n, g_val, g_val);g_val; // 次线程2 每次都需改这个全局变量sleep(1);} }int main() {pthread_t t1, t2; // 创建两个线程pthread_create(t1, NULL, threadHandler1, NULL);pthread_create(t2, NULL, threadHandler2, NULL);// 主线程运行while (true){printf(我是主线程我正在运行... g_val: %p g_val: %d\n, g_val, g_val);sleep(1);}return 0; }结果无论是主线程还是次线程当其中的一个线程出现修改行为时其他线程也会同步更改  多个线程访问同时访问一个资源不加以保护的话势必会造成影响当然这都是后话了加锁相关内容。 4、编程难度提高编写与调试一个多线程程序需要考虑许多问题诸如 加锁、同步、互斥 的等面对多个执行流时调试也是非常困难的。 三线程用途 合理的使用 多线程可以提高 CPU 计算密集型程序的效率 合理的使用 多线程可以提高 IO 密集型程序中用户的体验具体表现为用户可以一边下载一边做其他事情 三、

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

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

相关文章

茂名免费自助建站模板网站域名查询ip地址

链接:http://www.cnblogs.com/BeyondAnyTime/archive/2012/05/23/2514964.html

网站开发成本预算吴川市建设工程公司网站

Title 题目 Improved breast cancer histological grading using deep learning 使用深度学习改善乳腺癌组织学分级 01 文献速递介绍 乳腺癌组织学分级是乳腺癌中一个确立的临床变量,它包括来自三个方面的信息,即小管形成程度、核多态性和有丝分裂计…

邢台营销型网站制作邢台邯郸做网站

📝前言: 这篇文章主要讲解一下条件判断语句if和循环语句while,for在python中需要注意的地方。 建议已有一定了解(对语句的执行逻辑清楚)的读者观看,如果对条件判断和循环的执行逻辑不太清楚,也可…

手机网站域名哪里注册番禺品牌型网站

对象的克隆 1、克隆即复制的意思,对象的克隆,意味着生成一个对象,这个对象和某个对象的属性和行为是一致的,但是这个对象和源对象是两个不同的对象。实现对象的克隆,方法是实现Cloneable接口,否则会报异常C…

网站销售流程邹平建设局网站

实现的基本功能: 登录时,需要输入姓名,然后选择作为管理者还是普通用户。选择成功后选择想要实现的功能。管理者的目录下方有有五个功能,而普通用户有4个功能,如下图 首先我们要建立Book这个类,里面包含书…

哪个通讯公司的网络好合肥优化营商环境

LOGO是一个网站的形象代表或者说是品牌的象征,用户记住了网站LOGO,就相当于记住了网站,因此,自己建网站时要融入网站LOGO的设计,潜移默化地把LOGO形象植入用户脑海中,把网站与LOGO紧密连接在一起&#xff0…

做公司的网站大概多少钱湖南省建设厅纪检组长

基于Spring Boot的夕阳红公寓管理系统的设计与实现 摘 要 如今社会上各行各业,都在用属于自己专用的软件来进行工作,互联网发展到这个时候,人们已经发现离不开了互联网。互联网的发展,离不开一些新的技术,而新技术的…

阿里云做企业网站西部数码网站管理助手 卸载

OpenFireOpenFire 是采用Java开发的基于XMPP(Jabber)协议,开源实时协作(RTC)服务器。Smack 是用 Java编 写的XMPP客户端代码库,是 spark 的核心开源界总是有许多有趣的东东,这三个合起来就是一个完整的XMPP IM 实现。OpenFire ——服务器端Sp…

农产品网站建设的主要工作营销推广策划及渠道

摘要:开发高效的夜视行人检测系统对于提升夜间安全和监控效能至关重要。本篇博客详尽介绍了如何利用深度学习技术搭建一个夜视行人检测系统,并提供了完整的实现代码。本系统采用了先进的YOLOv8算法,并与YOLOv7、YOLOv6、YOLOv5进行了性能比较…

网站建设咨询宿迁房价下跌最惨小区

引言 最近在研究Vue打包成app,给我的报价器搞一个移动端,奈何没有安卓手机用于测试。所以想到安装一个安卓模拟器。 看了下目前主流的安卓模拟器基本都不支持Mac版本。网易的mumu目前来看还是只支持Intel芯。 1. 简单版(仅M系)…

建设网站困难的解决办法建设集团属于什么单位

以下示例显示如何获取选定的行或选定的列,或如何选择JTable组件中的多个单元格。要侦听选择事件,我们可以JTable通过调用JTable.getSelectionModel().addListSelectionListener()方法将选择侦听器添加到组件。该方法接受实现ListSelectionListener接口的…

哈尔滨市住房和城乡建设局局网站免费 网站管理系统

栈 思路: 思路与 力扣105. 从前序与中序遍历序列构造二叉树 相同;差异的地方: 从后序遍历数组尾部向前遍历;(根节点在尾部)一直迭代“最右”节点,将其挂载到栈顶(“根”节点&#x…

手机版网站开发框架pdf在线看wordpress

1.3.1 供给侧 技术层面:从实验室走向大规模的商用。 数据层面:数据正式成为重要的生产要素。 市场:供需互促的正向市场环境建立。 资本:走出炒作泡沫,聚焦价值领域。 平台:大厂普遍开放生态。 MORE&am…

建设网站的好处有哪些梧州房源信息网

欢迎关注我的CSDN:https://spike.blog.csdn.net/ 本文地址:https://spike.blog.csdn.net/article/details/132665807 BFloat16 类型是 16 位的浮点数格式,可以用来加速深度学习的计算和存储。BFloat16 类型的特点是保留 32 位浮点数&#xff…

帮企业建设网站销售沈阳房产网

【Python】一文详细介绍 plt.rc_context() 在 Matplotlib 中的原理、作用、注意事项 🌈 个人主页:高斯小哥 🔥 高质量专栏:Matplotlib之旅:零基础精通数据可视化、Python基础【高质量合集】、PyTorch零基础入门教程&a…

湖南营销型网站建设 皆来磐石网络最佳的资源搜索引擎

背景 金融、银行业等对数据的安全有着较高的要求,同城容灾建设方案,在绝大多数场景下可以保证业务数据的安全性,但是在极端情况下,如遇不可抗力因素等,要保证数据的安全性,就需要采取跨地域的容灾方案。 …

网站seo排名优化方法班级优化大师官方网站

用J中的多维数组进行Arrays.fill如何在不使用循环的情况下用Java填充多维数组? 我试过了:double[][] arr new double[20][4];Arrays.fill(arr, 0);结果为java.lang.ArrayStoreException: java.lang.Double提前致谢!11个解决方案87 votes这是…

400电话网络推广微信网站成都网站建设龙兵

实例: 官方解释:如果需要后端排序,需将sortable设置为custom,同时在 Table 上监听sort-change事件,在事件回调中可以获取当前排序的字段名和排序顺序,从而向接口请求排序后的表格数据。 1.table上要加 sort-change"sortCha…

南京网站建设王道下拉強新闻稿件代发平台

1.EXCEL诞生的意义 1.1 找到想要的数据 1.2 提升输入速度 2.数据分析与可视化操作 目的是提升数据的价值和意义 3.EXCEL使用的内在意义和外在形式 4.EXCEL的价值 4.1 解读及挖掘数据价值 4.2 协作板块 4.3 展示专业度 4.4 共享文档内容 5.人的需求》》软件功能

高碑店建设局网站网页如何制作网站

flutter开发实战-获取Widget的大小及位置 最近开发过程中需要获取Widget的大小及位置,这时候就需要使用到了GlobalKey了和WidgetsBinding.instance.addPostFrameCallback了 一、addPostFrameCallback 该函数的作用: flutter中的界面组件Widget每一帧…