JVM系列——Java与线程,介绍线程原理和操作系统的关系
并发不一定要依赖多线程(如PHP中很常见的多进程并发)。
但是在Java里面谈论并发,基本上都与线程脱不开关系。因此我们讲一下从Java线程在虚拟机中的实现。
线程的实现
线程是比进程更轻量级的调度执行单位。
线程的引入,可以把一个进程的资源分配和执行调度分开,各个线程既可以共享进程资源(内存地址、文件I/O等),又可以独立调度。
目前 线程是Java里面进行处理器资源调度的最基本单位,如果日后能成功为Java引入纤程 (Fiber)的话,可能就会改变这一点。
主流的操作系统都提供了线程实现,因此Java语言提供了在不同硬件和操作系统平台下对线程操作的统一 处理。每个已经调用过start( )方法且还未结束的java.lang.Thread类的实例就代表着一个线程。
Native方法:
Thread类与大部分的Java类库API有着显著差别,它的所有关键方法都被声明为Native。
在 Java类库API中,一个Native方法往往就意味着这个方法没有使用或无法使用平台无关的手段来实现 (当然也可能是为了执行效率而使用Native方法,不过通常最高效率的手段也就是平台相关的手 段)。
正因为这个原因,本节的标题被定为“线程的实现”而不是“Java线程的实现”。
在后面的实现方式中,将Java的技术背景放下,以一个通用的应用程序的角度来看看线程是如何实现的。
实现线程的三种方式:
实现线程主要有三种方式:
- 使用内核线程实现(1 : 1实现)
- 使用用户线程实现(1 : N实现)
- 使用用户线程加轻量级进程混合实现(N : M 实现)。
内核线程实现
使用内核线程实现的方式也被称为1:1实现。内核线程(Kernel-Level Thread,KLT)就是直接由操作系统内核(Kernel,下称内核)支持的线程。
这种线程由内核来完成线程切换,内核通过操纵调度器(Scheduler)对线程进行调度,并负责将线程的任务映射到各个处理器上。
每个内核线程可以视为内核的一个分身,这样操作系统就有能力同时处理多件事情,支持多线程的内核就称为多线程内核(Multi-Threads Kernel)。
轻量级进程
程序一般不会直接使用内核线程,而是使用内核线程的一种高级接口——轻量级进程(Light Weight Process,LWP)。
轻量级进程就是我们通常意义上所讲的线程,由于每个轻量级进程都由一个内核线程支持,因此只有先支持内核线程,才能有轻量级进程。这种轻量级进程与内核线程之间1:1 的关系称为一对一的线程模型。
由于内核线程的支持,每个轻量级进程都成为一个独立的调度单元,即使其中某一个轻量级进程在系统调用中被阻塞了,也不会影响整个进程继续工作
轻量级进程也具有它的局限性:
- 首先,由于是基于内核线程实现的,所以各种线程操作,如创建、析构及同步,都需要进行系统调用。
而系统调用的代价相对较高,需要在用户态(User M ode)和内核态(Kernel M ode)中来回切换
- 每个 轻量级进程都需要有一个内核线程的支持,因此轻量级进程要消耗一定的内核资源(如内核线程的栈空间),因此一个系统支持轻量级进程的数量是有限的
用户线程实现
使用用户线程实现的方式被称为1:N实现。
广义上来讲,一个线程只要不是内核线程,都可以认 为是用户线程(User Thread,UT)的一种。
因此从这个定义上看,轻量级进程也属于用户线程,但轻量级进程的实现始终是建立在内核之上的,许多操作都要进行系统调用,因此效率会受到限制,并不具备通常意义上的用户线程的优点。
而狭义上的用户线程指的是完全建立在用户空间的线程库上。
系统内核不能感知到用户线程的存在及如何实现的。
用户线程的建立、同步、销毁和调度完全在用户态中完成,不需要内核的帮助。
如果程序实现得当,这种线程不需要切换到内核态,因此操作可以是非常快速且低消耗的,也能够支持规模更大的线程数量。
部分高性能数据库中的多线程就是由用户线程实现的。
这种进程与用户线程之 间1:N的关系称为一对多的线程模型。
权衡
用户线程的优势在于不需要系统内核支援,劣势也在于没有系统内核的支援。
所有的线程操作都 需要由用户程序自己去处理。
线程的创建、销毁、切换和调度都是用户必须考虑的问题,而且由于操作系统只把处理器资源分配到进程,那诸如“阻塞如何处理”“多处理器系统中如何将线程映射到其他处理器上”这类问题解决起来将会异常困难,甚至有些是不可能实现的。
因为使用用户线程实现的程序通常都比较复杂,除了有明确的需求外(譬如以前在不支持多线程的操作系统中的多线程程序、需要 支持大规模线程数量的应用),一般的应用程序都不倾向使用用户线程。
Java、Ruby等语言都曾经使 用过用户线程,最终又都放弃了使用它。但是近年来许多新的、以高并发为卖点的编程语言又普遍支 持了用户线程,譬如Golang、Erlang等,使得用户线程的使用率有所回升。
混合实现
线程除了依赖内核线程实现和完全由用户程序自己实现之外,还有一种将内核线程与用户线程一起使用的实现方式,被称为N:M 实现。
在这种混合实现下,既存在用户线程,也存在轻量级进程。
用户线程还是完全建立在用户空间中,因此用户线程的创建、切换、析构等操作依然廉价,并且可以支持大规模的用户线程并发。
而操作系统支持的轻量级进程则作为用户线程和内核线程之间的桥梁,这样可以使用内核提供的线程调度功能及处理器映射,并且用户线程的系统调用要通过轻量级进程来完成,这大大降低了整个进程被完全阻塞的风险。
在这种混合模式中,用户线程与轻量级进程的数量 比是不定的,是N:M 的关系,这种就是多对多的线程模型。
许多UNIX系列的操作系统,如Solaris、HP-UX等都提供了M:N的线程模型实现。在这些操作系统上的应用也相对更容易应用M :N的线程模型。
Java线程的实现
Java线程如何实现并不受Java虚拟机规范的约束,这是一个与具体虚拟机相关的话题。
Java线程在 早期的Classic虚拟机上(JDK 1.2以前),是基于一种被称为“绿色线程”(Green Threads)的用户线程实现的。
但从JDK 1.3起,“主流”平台上的“主流”商用Java虚拟机的线程模型普遍都被替换为基于操作系统原生线程模型来实现,即采用1:1的线程模型。
HotSpot实现
以HotSpot为例,它的每一个Java线程都是直接映射到一个操作系统原生线程来实现的,而且中间没有额外的间接结构,所以HotSpot自己是不会去干涉线程调度的(可以设置线程优先级给操作系统提供调度建议),全权交给底下的操作系统去处理。
所以何时冻结或唤醒线程、该给线程分配多少处理器执行时间、该把线程安排给哪个处理器核心去执行等,都是由操作系统完成的,也都是由操作系统全权决定的。
操作系统支持怎样的线程模型,在很大程度上会影响上面JVM的线程是怎样映射的。但操作系统的线程模型在不同的平台上很难达成一致,因此《Java虚拟机规范》中才不去限定Java线程需要使用哪种线程模型来实现。
线程模型只对线程的并发规模和操作成本产生影响,对Java程序的编码和运行过程来说,这些差异都是完全透明的。
Java线程调度
线程调度是指系统为线程分配处理器使用权的过程。调度主要方式有两种,分别是协同式
(Cooperative Threads-Scheduling)线程调度和抢占式(Preemptive Threads-Scheduling)线程调度。
如果使用协同式调度的多线程系统,线程的执行时间由线程本身来控制,线程把自己的工作执行完了之后,要主动通知系统切换到另外一个线程上去。
协同式调度
协同式多线程的最大好处是实现简单,而且由于线程要把自己的事情干完后才会进行线程切换,切换操作对线程自己是可知的,所以一般没有什么线程同步的问题。
Lua语言中的“协同例程”就是这类实现。它的坏处也很明显:
线程执行时间不可控制,甚至如果一个线程的代码编写有问题,一直不告知系统进行线程切换,那么程序就会一直阻塞在
那里。很久以前的Windows 3.x系统就是使用协同式来实现多进程多任务的,那是相当不稳定的,只要有一个进程坚持不让出处理器执行时间,就可能会导致整个系统崩溃。
抢占式调度
如果使用抢占式调度的多线程系统,那么每个线程将由系统来分配执行时间,线程的切换不由线程本身来决定。
譬如在Java中,有Thread::yeld()方法可以主动让出执行时间,但是没办法主动获取执行时间。
在这种实现线程调度的方式下:
- 线程的执行时间是系统可控的
- 不会有一个线程导致整个进程甚至整个系统阻塞的问题。
Java使用的线程调度方式就是抢占式调度。与前面所说的Windows 3.x的例子相对,在Windows 9x/NT内核中就是使用抢占式来实现多进程的。
当一个进程出了问题,我们还可以使用任务管理器把这个进程杀掉,而不至于导致系统崩溃。
线程优先级
虽然说Java线程调度是系统自动完成的,但是我们仍然可以“建议”操作系统给某些线程多分配一 点执行时间,另外的一些线程则可以少分配一点——这项操作是通过设置线程优先级来完成的。
Java 语言一共设置了10个级别的线程优先级(Thread.M IN_PRIORITY至Thread.M AX_PRIORITY)。在
两个线程同时处于Ready状态时,优先级越高的线程越容易被系统选择执行。
不过,线程优先级并不是一项稳定的调节手段,很显然因为主流虚拟机上的Java线程是被映射到系统的原生线程上来实现的,所以线程调度最终还是由操作系统说了算。
尽管现代的操作系统基本都提供线程优先级的概念,但是并不见得能与Java线程的优先级一一对应,如Solaris中线程有 2147483648(2的31次幂)种优先级,但Windows中就只有七种优先级。Windows平台的虚拟机中使用了除 THREAD_PRIORITY_IDLE之外的其余6种线程优先级,因此在Windows下设置线程优先级为1和2、3 和4、6和7、8和9的效果是完全相同的。
线程优先级并不是一项稳定的调节手段。
这不仅仅体现在某些操作系统上不同的优先级实际会变得相同这一点上;
还有其他情况让我们不能过于依赖线程优先级: 优先级可能会被系统自行改变,例如在Windows系统中存在一个叫“优先级推进器”的功能(Priority Boosting,当然它可以被关掉),大致作用是当系统发现一个线程被执行得特别频繁时,可能会越过线程优先级去为它分配执行时间,从而减少因为线程频繁切换而带来的性能损耗。
因此,我们并不能在程序中通过优先级来完全准确判断一组状态都为Ready的线程将会先执行哪一个。
状态转换
Java语言定义了6种线程状态,在任意一个时间点中,一个线程只能有且只有其中的一种状态,并且可以通过特定的方法在不同状态之间转换。这6种状态分别是:
- 新建(New): 创建后尚未启动的线程处于这种状态。
- 运行(Runnable): 包括操作系统线程状态中的Running和Ready,也就是处于此状态的线程有可能正在执行,也有可能正在等待着操作系统为它分配执行时间。
- 无限期等待(Waiting): 处于这种状态的线程不会被分配处理器执行时间,它们要等待被其他线程显式唤醒。以下方法会让线程陷入无限期的等待状态:
- 没有设置Timeout 参数的O bject ::w ait ()方法;
- 没有设置Timeout 参数的T hread::join()方法;
- LockSupport::park()方法。
- **限期等待(Timed Waiting): **处于这种状态的线程也不会被分配处理器执行时间,不过无须等待被其他线程显式唤醒,一定时间之后会由系统自动唤醒。以下方法会让线程进入限期等待状态:
- Thread::sleep()方法
- 设置了Timeout参数的Object::wait()方法;
- 设置了Timeout参数的T hread::join()方法;
- LockSupport::parkNanos()方法;
- LockSupport::parkUntil()方法。
- 阻塞(Blocked): 线程被阻塞了,
“阻塞状态”与“等待状态”的区别是“阻塞状态”在等待着获取到一个排它锁,这个事件将在另外一个线程放弃这个锁的时候发生; 而“等待状态”则是在等待一段时 间,或者唤醒动作的发生。在程序等待进入同步区域的时候,线程将进入这种状态。
- 结束(Terminated):已终止线程的线程状态,线程已经结束执行。
上述6种状态在遇到特定事件发生时会互相转换,它们的转换关系如下图所示:
相关文章:
JVM系列——Java与线程,介绍线程原理和操作系统的关系
并发不一定要依赖多线程(如PHP中很常见的多进程并发)。 但是在Java里面谈论并发,基本上都与线程脱不开关系。因此我们讲一下从Java线程在虚拟机中的实现。 线程的实现 线程是比进程更轻量级的调度执行单位。 线程的引入,可以把一个进程的资源分配和执行调…...
C++打开文件夹对话框之BROWSEINFO
头文件 #include <shlobj.h> #include <windows.h> #include <stdio.h> using namespace std; 案例 string chooseFile(void) {//用户选择的路径,可以是TCHAR szBuffer[MAX_PATH] {0};然后再使用TCHAR 转char字符串,此处可以直接使…...
Nuxt项目配置、目录结构说明-实战教程基础-Day02
Nuxt项目配置、目录结构说明-实战教程基础-Day02一、Nuxt项目结构1.1资源目录1.2 组件目录1.3 布局目录1.4 中间件目录1.5 页面目录1.6 插件目录1.7 静态文件目录1.8 Store 目录1.9 nuxt.config.js 文件1.10 package.json 文件其他:别名二、项目配置2.1 build2.2 cs…...
单链表的头插,尾插,头删,尾删等操作
前言顺序表要求是具有连续的物理空间,并且数据的话是在这些空间当中是连续的存储。但这样会带来很多问题,比如说在头部或者说中间插入的话,效率不是很高;并且申请空间可能需要扩容,并且越往后一般来说都是异地扩容&…...
Qt扫盲-QProcess理论总结
QProcess理论使用总结一、概述二、使用三、通过 Channel 通道通信四、同步进程API五、注意事项1. 平台特性2. 不能实时读取一、概述 QProcess 其实更多的是与外面进程进行交互的一个工具类,通过这个类来启动外部进程,获取这个进程的标准输出,…...
JAVA进阶 —— Steam流
目录 一、 引言 二、 Stream流概述 三、Stream流的使用步骤 1. 获取Stream流 1.1 单列集合 1.2 双列集合 1.3 数组 1.4 零散数据 2. Stream流的中间方法 3. Stream流的终结方法 四、 练习 1. 数据过滤 2. 数据操作 - 按年龄筛选 3. 数据操作 - 演员信息要求…...
Ubuntu Protobuf 安装(测试有效)
安装流程 下载软件 下载自己要安装的版本:https://github.com/protocolbuffers/protobuf 下载源码编译: 系统环境:Ubuntu16(其它版本亦可),Protobuf-3.6.1 编译源码 cd protobuf# 当使用 git clone 下来的…...
驱动程序开发:FTP服务器和OpenSSH的移植与搭建、以及一些笔记
目录一、FTP服务器移植与搭建1、在ubuntu下安装vsftpd2、在window下安装FileZilla3、移植vsftpd到开发板上4、Filezilla 连接测试5、注意点二、开发板 OpenSSH 移植与使用1、移植 zlib 库2、移植 openssl 库3、移植 openssh 库4、openssh 使用测试三、关于u-boot上的操作及根文…...
优化改进YOLOv5算法之添加GIoU、DIoU、CIoU、EIoU、Wise-IoU模块(超详细)
目录 1、IoU 1.1 什么是IOU 1.2 IOU代码 2、GIOU 2.1 为什么提出GIOU 2.2 GIoU代码 3 DIoU 3.1 为什么提出DIOU 3.2 DIOU代码 4 CIOU 4.1 为什么提出CIOU 4.2 CIOU代码 5 EIOU 5.1 为什么提出EIOU 5.2 EIOU代码 6 Wise-IoU 7 YOLOv5中添加GIoU、DIoU、CIoU、…...
windows电脑pc如何使用svn获取文档和代码
一、安装svn 下载链接 也可通过其他方式下载 二、使用 2.1 随便找一个文件夹 2.2 点击右键,选择SVN Checkout 2.3输入网址 如当你在网页上访问时地址为https://10.197.78.78/!/#aaa/view/head/bbb 在这里不能直接填入,而是 https://10.197.78.78/sv…...
ROS1学习笔记:tf坐标系广播与监听的编程实现(ubuntu20.04)
参考B站古月居ROS入门21讲:tf坐标系广播与监听的编程实现 基于VMware Ubuntu 20.04 Noetic版本的环境 文章目录一、创建功能包二、创建代码2.1 以C为例2.1.1 配置代码编译规则2.1.2 编译整个工作空间2.1.2 配置环境变量2.1.4 执行代码2.2 以Python为例2.2.1 配置代码…...
力扣解法汇总1590. 使数组和能被 P 整除
目录链接: 力扣编程题-解法汇总_分享记录-CSDN博客 GitHub同步刷题项目: https://github.com/September26/java-algorithms 原题链接:力扣 描述: 给你一个正整数数组 nums,请你移除 最短 子数组(可以为 …...
Spring源码阅读(基础)
第一章:bean的元数据 1.bean的注入方式: 1.1 xml文件 1.2 注解 Component(自己写的类才能在上面加这些注解) 1.3配置类: Configuration 注入第三方数据源之类 1.4 import注解 (引用了Myselector类下…...
服务搭建篇(九) 使用GitLab+Jenkins搭建CI\CD执行环境 (上) 基础环境搭建
1.前言 每当我们程序员开发在本地完成开发之后 , 都要部署到正式环境去使用 , 在一些传统的运维体系中 , 开发与运维都是割裂的 , 开发人员不允许操作正式服务器 , 服务器只能通过运维团队来操作 , 这样可以极大的提高服务器的安全性 , 不经过安全保护的开放服务器 , 对于黑客…...
CDC 长沙站丨云原生技术研讨会:数字兴链,云化未来!
一、活动信息:活动主题:CDC 长沙站丨云原生技术研讨会活动时间:2023 年 3 月 14 日下午 14:30-17:30活动地点:长沙市岳麓区-拓维信息总部 1 楼多功能厅活动参与方式:免门票参与,戳此…...
A.特定领域知识图谱知识推理方案:知识图谱推理算法综述[二](DTransE/PairRE:基于表示学习的知识图谱链接预测算法)
推荐参考文章: A.特定领域知识图谱知识推理方案:知识图谱推理算法综述[一](基于距离的翻译模型:TransE、TransH、TransR、TransH、TransA、RotatE) A.特定领域知识图谱知识推理方案:知识图谱推理算法综述[二](DTransE/PairRE:基于表示学习的知识图谱链接预测算法) A.…...
香港酒店模拟分析项目报告--使用tableau、python、matlab
转载请标记本文出处 软件:tableau、pycharm、关系型数据库:MySQL 数据大量分析考虑电脑性能的情况。 文章目录前言一、爬虫是什么?二、使用tableau数据可视化1.引入数据1.1 制作直方图-各地区酒店数量条形图1.2 各地区酒店均价1.3 价格等级堆…...
第18天-商城业务(商品检索服务,基于Elastic Search完成商品检索)
1.构建商品检索页面 1.1.引入依赖 <!-- thymeleaf模板引擎 --><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-thymeleaf</artifactId></dependency><!-- 热更新 --><…...
5.2 对射式红外传感器旋转编码器计次
对射式红外传感器1.1 接线图VCC GND分别接电源的正负极DO数字输出端,随意选择一个GPIO口1.2 硬件原理当挡光片或者编码盘在对射式红外传感器中间经过时,DO就会输出电平变化信号,电平跳变信号触发STM32 PB14号口中断,在中断函数中执…...
【数据库概论】第九章 关系查询处理和查询优化
第九章 关系查询处理和查询优化 本章主要介绍关系数据库查询管理和查询优化,主要分为代数优化(又称逻辑优化)和物理优化(也称非代数优化)。 9.1 关系型数据库系统的查询处理 查询处理是关系型数据库管理系统执行查询…...
(WIP) my cloud test bed (by quqi99)
作者:张华 发表于:2023-03-10 版权声明:可以任意转载,转载时请务必以超链接形式标明文章原始出处和作者信息及本版权声明 问题 想创建一个local local test bed, 用来方便做各种云实验,如openstack, k8s, ovn, lxd等…...
git | git 2023 详细版
文章目录一、Git命令1.2 设计用户签名1.3 初始化本地库1.4 查看本地库状态1.5 添加至暂存区1.6 从暂存区删除1.7 将暂存区的文件提交到本地库1.8 查看版本信息二、Git分支2.1 查看分支2.2 创建分支2.3 切换分支2.4 合并分支三、GitHub3.1 代码克隆clone3.2 给库取别名3.3 推送本…...
camunda流程引擎基本使用(笔记)
文章目录一、camunda基础1.1 安装与部署流程引擎1.2 流程引擎结构1.3 流程引擎的基本使用1.3.1 创建一个BPMN Diagram1.3.2 实现一个外部工作者1.3.3 部署流程1.3.4 创建一个流程实例并消费1.3.5 向流程中添加用户任务1.3.6 添加网关1.3.7 业务规则二、Java 集成流程引擎2.1 为…...
JS之数据结构与算法
前言数据结构是计算机存储、组织数据的方式,算法是系统描述解决问题的策略。了解基本的数据结构和算法可以提高代码的性能和质量。也是程序猿进阶的一个重要技能。手撸代码实现栈,队列,链表,字典,二叉树,动态规划和贪心算法1.数据结构篇1.1 栈栈的特点:先进后出clas…...
CnOpenData·A股上市企业数字化转型指数数据
一、数据简介 企业数字化转型是近年来中国社会各界重点关注的领域,但基础数据的不完善在很大程度上制约了相关科学研究的开展。构建合理、科学的数字化转型指标体系有利于学者定量地研究企业数字化的相关问题,也有利于衡量企业的数字化水平。广东金融学院…...
VMware16pro虚拟机安装全过程
很多时候需要用到Linux系统,简单的一种方式可以是:Windows系统运行Linux(Windows Subsystem for Linux)不过有些时候还是需要虚拟机来运行Linux,也更方便点,比如在做嵌入式系统的烧录等操作都需要Linux环境…...
阿里云第六代云服务器最新价格表(计算型c6、通用型g6和内存型r6)
目前阿里云第六代云服务器有计算型c6、通用型g6和内存型r6实例。计算型c6实例有2核4G、4核8G、8核16G配置可选,主要适用于网站应用、批量计算、视频编码等场景。通用型g6实例有2核8G、4核16G、8核32G配置可选,适用于各种类型的企业级应用,网站…...
微小目标识别研究(2)——基于K近邻的白酒杂质检测算法实现
文章目录实现思路配置opencv位置剪裁实现代码自适应中值滤波实现代码动态范围增强实现代码形态学处理实现代码图片预处理效果计算帧差连续帧帧差法原理和实现代码实现代码K近邻实现基本介绍实现代码这部分是手动实现的,并没有直接调用相关的库完整的代码——调用ope…...
2022-06-14至2022-08-11 关于复现MKP算法的总结与反思
Prerequisite 自2022年6月14日至2022年8月11日的时间内,我致力于完成A Hybrid Approach for the 0–1 Multidimensional Knapsack problem 论文的复现工作,此次是我第一次进行组合优化方向的学习工作,下面介绍该工作内容发展过程以及该工作结…...
IBMMQ教程二(window版安装)
下载下载地址:https://public.dhe.ibm.com/ibmdl/export/pub/software/websphere/messaging/mqadv/我这里选择的是9.1.0.0版本安装将下载完成的压缩包解压双击Setup.exe直接运行点击软件需求查看系统配置是否满足,右边绿色的对号说明满足需求,…...
做住宿的网站/iis7站长工具
1、布署ApplicationErrorLog未处理异常处理组件。A、引用相关组件。B、修改Web.config<?xml version"1.0"?><configuration><configSections><section name"ApplicationErrorLogData"type"Lion.Web.ApplicationErrorLog.Confi…...
智能seo系统/合肥seo整站优化
2019独角兽企业重金招聘Python工程师标准>>> 人心如良苗,得养乃滋长;苗以泉水灌,心以理义养。一日不读书,胸臆无佳想。一月不读书,耳目失精爽。 转载于:https://my.oschina.net/reesechou/blog/389110...
做金属的网站/成都本地推广平台
很早就听说Charles Petzold的《编码》非常值得一看,特地趁着京东6.18下单,现将阅读收获进行整理,大致分为三篇进行讲解。 第一章 至亲密友 编码的含义:一种传递信息的方式。 思路转换过程:手电筒写字母(难…...
怎样去同行网站做外连接/网站seo如何做好优化
为什么80%的码农都做不了架构师?>>> 网络yum配置 # cd /etc/yum.repos.d/ # wget http://mirrors.163.com/.help/CentOS6-Base-163.repo # vi CentOS6-Base-163.repo : % s/\$releasever/6.6/g 编辑文件,把文件里面的$releasever全部替换…...
网站开发需要甲方提供什么/如何制作网址链接
1.使用CTime类 CString str; //获取系统时间 CTime tm; tmCTime::GetCurrentTime(); strtm.Format("现在时间是%Y年%m月%d日 %X"); MessageBox(str,NULL,MB_OK); 2: 得到系统时间日期(使用GetLocalTime) SYSTEMTIME st; CString strDate,…...
深圳市官方网站/seo技术培训宁波
现在一直在做的项目,数据量相对也不小,开始的时候没有觉得,因为是刚开始,数据量还很小,在程序使用过程中速度还挺快,但是随着数据量的不停的增长,发现程序越来越慢,甚至出现了超时的…...