百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术教程 > 正文

垃圾收集调优概述

mhr18 2025-01-04 21:35 13 浏览 0 评论

Java应用的多样性与垃圾收集器:Java SE应用广泛,HotSpot VM提供多种垃圾收集器以适应不同需求,默认根据应用运行的计算机类型选择,但可能不满足所有应用,特定场景下需手动选择和调优。

1 垃圾收集器相关内容

定义与功能

自动管理内存:垃圾收集器自动处理应用动态内存分配请求,包括向操作系统分配和回收内存、按应用请求分配内存、确定内存使用情况并回收未使用内存。

提高效率的技术:采用分代回收与老化机制聚焦于可能含大量可回收内存的堆区域;利用多线程并行操作或在后台与应用并发执行长耗时操作;通过压缩活动对象回收更大连续空闲内存。

选择垃圾收集器的重要性

解放开发者:使开发者无需手动管理动态内存,避免内存管理相关错误,但增加运行时开销。

影响性能的场景:对于数据量大、线程多、事务率高的应用,垃圾收集器选择至关重要。根据Amdahl定律,多数工作负载不能完全并行化,垃圾收集开销应尽量降低,否则在扩展到大型系统时,小系统中可忽略的吞吐量问题会成为瓶颈,但优化瓶颈可大幅提升性能。

不同收集器的适用场景:串行收集器通常适用于大多数小应用(堆大小约100MB以下),大型多线程应用且运行在大内存多处理器机器上时,G1收集器通常是更好选择(默认情况下)。

2 人体工程学(Ergonomics)

人体工程学是指JVM和垃圾收集启发式算法(如基于行为的启发式算法)如何改进应用程序性能的过程。

JVM默认设置

  • JVM为垃圾收集器、堆大小和运行时编译器提供平台依赖的默认选择,以满足不同类型应用程序的需求,同时减少命令行调整的需求。
  • 基于行为的调整动态优化堆大小以满足应用程序的指定行为。

垃圾收集器、堆和运行时编译器的默认选择

  • 在服务器级机器上,默认使用G1收集器,否则使用串行收集器。
  • GC线程的最大数量受堆大小和可用CPU资源的限制。
  • 初始堆大小为物理内存的1/64。
  • 最大堆大小为物理内存的1/4。
  • 使用分层编译器,同时使用C1和C2。

注意:如果VM检测到超过两个处理器和堆大小大于或等于1792MB,则认为机器为服务器级。

基于行为的调整

Java HotSpot VM垃圾收集器可以配置为优先满足两个目标之一:最大暂停时间和应用程序吞吐量。如果满足首选目标,收集器将尝试最大化另一个目标。这些目标并不总是能够完全满足。

最大暂停时间目标

  • 暂停时间是垃圾收集器停止应用程序并回收不再使用的空间的持续时间。
  • 最大暂停时间目标的意图是限制这些暂停中最长的暂停时间。
  • 垃圾收集器通过命令行选项-XX:MaxGCPauseMillis=来指定,其中表示期望的暂停时间(以毫秒为单位)。

吞吐量目标

  • 吞吐量目标以垃圾收集时间来衡量,垃圾收集之外的时间是应用程序时间。
  • 通过命令行选项-XX:GCTimeRatio=nnn来指定,其中垃圾收集时间与应用程序时间的比例为1/(1+nnn)。

占用空间(Footprint)

  • 如果吞吐量和最大暂停时间目标都已满足,垃圾收集器会减小堆大小,直到其中一个目标(通常是吞吐量目标)无法满足。
  • 可以使用-Xms=-Xmx=分别设置垃圾收集器可以使用的最小和最大堆大小。

调整策略

  • 堆的大小会增长或缩小,以支持选定的吞吐量目标。
  • 了解堆调整策略,例如选择最大堆大小和最大暂停时间目标。
  • 除非您知道需要大于默认最大堆大小的堆,否则不要选择最大堆大小。
  • 选择一个对您的应用程序足够的吞吐量目标。
  • 应用程序行为的变化可能导致堆的增长或缩小。
  • 如果堆增长到最大大小且吞吐量目标未达到,则最大堆大小对于吞吐量目标来说太小。
  • 如果吞吐量目标可以实现,但暂停时间过长,则选择一个最大暂停时间目标。

通常,即使应用程序已达到稳态,堆的大小也会随着垃圾收集器尝试满足竞争目标而振荡。这在追求吞吐量目标(可能需要更大的堆)与最大暂停时间和最小占用空间(两者都可能需要较小的堆)之间存在竞争。

3 垃圾收集器实现

Java SE平台的一个优势是它为开发者屏蔽了内存分配和垃圾收集的复杂性。然而,当垃圾收集成为主要瓶颈时,了解一些实现细节是有用的。垃圾收集器对应用程序使用对象的方式做出了假设,这些假设反映在可调参数中,可以调整这些参数以提高性能,而不会牺牲抽象的强大能力。

一个对象被认为是垃圾,并且其内存可以被VM重复使用,当它不能再被任何其他活动对象的任何引用从运行程序中到达时。

一个理论上的最直接垃圾收集算法每次运行时都会遍历每一个可达对象。任何剩余的对象都被认为是垃圾。这种方法所需的时间与活动对象的数量成正比,这对于维护大量活动数据的大型应用程序来说是不切实际的。

Java HotSpot VM包含了许多不同的垃圾收集算法,除了ZGC外,都使用一种称为分代收集的技术。虽然简单的垃圾收集每次都会检查堆中的每一个活动对象,但分代收集利用大多数应用程序的几个经验观察属性来最小化回收未使用(垃圾)对象所需的工作。这些观察到的属性中最重要的是弱代假设,它指出大多数对象只存活很短的时间。


蓝色区域是对象寿命的典型分布。x轴显示以字节分配测量的对象寿命。y轴上的字节计数是具有相应寿命的对象的总字节。左侧的尖峰代表分配后不久就可以回收(换句话说,已经“死亡”)的对象。例如,迭代器对象通常只在单个循环期间存活。

代(Generations)

为了优化这种情况,内存以代(持有不同年龄对象的内存池)进行管理。当一代填满时,就会在该代发生垃圾收集。

绝大多数对象都在一个专门用于年轻对象的池(年轻代)中分配,大多数对象也在那里死亡。当年轻代填满时,它会导致一个次要收集,其中只收集年轻代;其他代的垃圾不会被回收。这种收集的成本,首先,与被收集的活动对象的数量成正比;一个充满死亡对象的年轻代可以非常快速地被收集。通常,在每次要收集期间,一部分从年轻代存活下来的对象被移动到老年代。最终,老年代填满并且必须被收集,导致一个主要收集,其中整个堆被收集。主要收集通常比次要收集持续时间更长,因为涉及的对象数量显著更多。

serial garbage collector内存分配

在启动时,Java HotSpot虚拟机在地址空间中预留了整个Java堆,但在需要之前不会为其分配任何物理内存。覆盖Java堆的整个地址空间被逻辑上划分为年轻代和老年代。为对象内存保留的完整地址空间可以被划分为年轻代和老年代。

年轻代由伊甸区(eden)和两个幸存者空间(survivor spaces)组成。大多数对象最初是在伊甸区分配的。在任何时候,都有一个幸存者空间是空的,它在垃圾收集期间作为伊甸区和另一个幸存者空间中活动对象的目的地;垃圾收集之后,伊甸区和源幸存者空间会变为空。在下一次垃圾收集中,两个幸存者空间的角色会交换。最近填充的空间成为了活动对象的来源,这些对象被复制到另一个幸存者空间中。对象以这种方式在幸存者空间之间复制,直到它们被复制了一定次数或者那里没有足够的空间了。这些对象随后被复制到老年代区域。这个过程也被称为老化(aging)。

性能考虑

垃圾收集的主要衡量标准是吞吐量和延迟。

吞吐量是在长时间内不花在垃圾收集上的总时间的百分比。吞吐量包括分配时间(但通常不需要调整分配速度)。延迟是应用程序的响应能力。垃圾收集暂停影响应用程序的响应能力。

用户对垃圾收集有不同的要求。例如,一些人认为对于Web服务器来说,正确的指标是吞吐量,因为垃圾收集期间的暂停可能是可以容忍的,或者简单地被网络延迟所掩盖。然而,在一个交互式图形程序中,即使是短暂的暂停也可能对用户体验产生负面影响。

一些用户对其他考虑因素敏感。占用空间是进程的工作集,以页面和缓存行来衡量。在物理内存有限或有许多进程的系统上,占用空间可能决定可扩展性。及时性是对象变得死亡和内存变得可用之间的时间,对于分布式系统来说是一个重要考虑因素,包括远程方法调用(RMI)。

通常,为特定一代选择大小是在这些考虑因素之间进行权衡。例如,一个非常大的年轻代可能会最大化吞吐量,但这是以牺牲占用空间、及时性和暂停时间为代价的。可以通过使用一个小的年轻代来最小化年轻代暂停,以牺牲吞吐量为代价。一代的大小选择不会影响另一代的收集频率和暂停时间。

没有一种正确的方法来选择一代的大小。最佳选择取决于应用程序使用内存的方式以及用户需求。因此,虚拟机选择的垃圾收集器并不总是最优的,并且可以通过命令行选项来覆盖;参见影响垃圾收集性能的因素。

吞吐量和占用空间测量

吞吐量和占用空间最好使用特定于应用程序的指标来衡量。

例如,可以使用客户端负载生成器来测试Web服务器的吞吐量。然而,由于垃圾收集导致的暂停时间可以通过检查虚拟机本身的诊断输出来轻松估计。命令行选项-verbose:gc在每次垃圾收集时打印有关堆和垃圾收集的信息。这里是一个例子:

[15,651s][info ][gc] GC(36) Pause Young (G1 Evacuation Pause) 239M->57M(307M) (15,646s, 15,651s) 5,048ms
[16,162s][info ][gc] GC(37) Pause Young (G1 Evacuation Pause) 238M->57M(307M) (16,146s, 16,162s) 16,565ms
[16,367s][info ][gc] GC(38) Pause Full (System.gc()) 69M->31M(104M) (16,202s, 16,367s) 164,581ms

输出显示了两次年轻代收集,随后是由应用程序通过调用System.gc()发起的完整收集。这些行以时间戳开头,表示自应用程序启动以来的时间。接下来是关于日志级别(info)和标签(gc)的信息。然后是GC标识编号。在这个例子中,有三个GC,编号为36、37和38。然后记录了GC的类型和启动GC的原因。之后,记录了一些关于内存消耗的信息,格式为“GC前已使用”->“GC后已使用”(“堆大小”)。

在示例的第一行中,239M->57M(307M)表示GC前使用了239MB,GC清理了大部分内存,但有57MB存活。堆大小为307MB。请注意,在示例中,完整GC将堆从307MB缩小到104MB。在内存使用信息之后,记录了GC的开始和结束时间以及持续时间(结束 - 开始)。

-verbose:gc命令是-Xlog:gc的别名。-Xlog是HotSpot JVM中用于日志记录的通用配置选项。它是一个基于标签的系统,其中gc是标签之一。要获取有关GC正在执行的操作的更多信息,可以配置日志记录以打印任何带有gc标签和其他标签的消息。此命令行为-Xlog:gc*

4 影响垃圾收集性能的因素

影响垃圾收集性能的两个最重要因素是总可用内存和专门分配给年轻代的堆比例。

总堆

影响垃圾收集性能的最重要因素是总可用内存。由于收集发生在代填满时,吞吐量与可用内存量成反比。

注意:以下关于堆的增长和收缩、堆布局和默认值的讨论以串行收集器为例。虽然其他收集器使用类似的机制,但这里提供的细节可能不适用于其他收集器。请参阅相关主题以获取其他收集器的类似信息。

影响代大小的堆选项

影响代大小的堆选项

堆中承诺空间和虚拟空间的区别。在虚拟机初始化时,为整个堆预留了空间。可以使用-Xmx选项指定预留空间的大小。如果-Xms参数的值小于-Xmx参数的值,则不是立即将所有预留的空间承诺给虚拟机。未承诺的空间在这张图中被标记为“虚拟”。堆的不同部分,即老年代和年轻代,可以根据需要增长到虚拟空间的限制。

一些参数是堆一部分与另一部分的比例。例如,参数–XX:NewRatio表示老年代相对于年轻代的大小。

默认堆大小选项值

默认情况下,虚拟机在每次收集时增长或收缩堆,以尝试保持每次收集时空闲空间与活动对象的比例在特定范围内。

此目标范围由选项-XX:MinHeapFreeRatio=<最小值>和-XX:MaxHeapFreeRatio=<最大值>设置为百分比,总大小由–Xms<最小值>和–Xmx<最大值>限制。

使用这些选项,如果一代中的空闲空间百分比降至40%以下,则该代扩展以维持40%的空闲空间,直到该代允许的最大大小。类似地,如果空闲空间超过70%,则该代收缩,以便只有70%的空间是空闲的,但要受到该代最小大小的限制。

Java SE中用于并行收集器的计算现在已用于所有垃圾收集器。对于客户端JVM,有一个类似的计算,结果得到的是比服务器JVM更小的最大堆大小。

以下是服务器应用程序堆大小的一般指南:

除非您遇到暂停问题,否则请尽可能多地授予虚拟机内存。默认大小通常太小。

将-Xms和-Xmx设置为相同的值可以通过消除虚拟机最重要的大小决定来增加可预测性。然而,如果做出了错误的选择,虚拟机就无法补偿。

一般来说,随着处理器数量的增加,增加内存分配,因为分配可以并行进行。

通过最小化Java堆大小来节省动态占用空间

如果您需要最小化应用程序的动态内存占用(执行期间消耗的最大RAM),则可以通过最小化Java堆大小来实现这一点。Java SE嵌入式应用程序可能需要这样做。

通过降低选项-XX:MaxHeapFreeRatio(默认值为70%)和-XX:MinHeapFreeRatio(默认值为40%)的值,使用命令行选项-XX:MaxHeapFreeRatio和-XX:MinHeapFreeRatio来最小化Java堆大小。将-XX:MaxHeapFreeRatio降低到低至10%,并且-XX:MinHeapFreeRatio已经显示出在不过多牺牲性能的情况下成功减小堆大小;然而,结果可能会因您的应用程序而有很大差异。尝试不同的这些参数值,直到它们尽可能低,同时仍然保持可接受的性能。

此外,您可以指定-XX:-ShrinkHeapInSteps,它立即将Java堆减少到目标大小(由参数-XX:MaxHeapFreeRatio指定)。使用此设置可能会遇到性能下降。默认情况下,Java运行时逐步将Java堆减少到目标大小;这个过程需要多次垃圾收集周期。

年轻代

在总可用内存之后,影响垃圾收集性能的第二大因素是专门分配给年轻代的堆比例。

年轻代越大,次要收集发生的频率就越低。然而,对于有界堆大小,较大的年轻代意味着较小的老年代,这将增加主要收集的频率。最佳选择取决于应用程序分配的对象的生命周期分布。

年轻代大小选项

默认情况下,年轻代大小由选项-XX:NewRatio控制。

例如,设置-XX:NewRatio=3意味着年轻代和老年代之间的比例是1:3。换句话说,eden和幸存者空间的总大小将是总堆大小的四分之一。

选项-XX:NewSize和-XX:MaxNewSize从下界和上界限制年轻代的大小。将这些设置为相同的值可以固定年轻代,就像将-Xms和-Xmx设置为相同的值可以固定总堆大小一样。这在调整年轻代时比-XX:NewRatio允许的整数倍更细粒度。

幸存者空间大小调整

您可以使用选项-XX:SurvivorRatio来调整幸存者空间的大小,但通常这对性能并不重要。

例如,-XX:SurvivorRatio=6将eden与一个幸存者空间的比例设置为1:6。换句话说,每个幸存者空间将是eden大小的六分之一,因此是年轻代大小的八分之一(不是七分之一,因为有两个幸存者空间)。

如果幸存者空间太小,则复制收集会直接溢出到老年代。如果幸存者空间太大,则它们无用地空着。在每次垃圾收集中,虚拟机选择一个阈值,即对象可以复制的次数,然后才变老。这个阈值被选择为保持幸存者半满。您可以使用日志配置-Xlog:gc,age来显示这个阈值和新代中对象的年龄。它也有助于观察应用程序的生命周期分布。


年轻代的最大大小是从总堆的最大大小和-XX:NewRatio参数的值计算出来的。-XX:MaxNewSize参数的“不受限”默认值意味着除非在命令行上指定了-XX:MaxNewSize的值,否则计算出的值不受-XX:MaxNewSize的限制。

以下是服务器应用程序的一般指南:

首先,决定您可以负担得起的虚拟机的最大堆大小。然后,将性能指标与年轻代大小进行对比,以找到最佳设置。请注意,最大堆大小应始终小于机器上安装的内存量,以避免过多的页面错误和抖动。

如果总堆大小固定,则增加年轻代大小需要减少老年代大小。保持老年代足够大,以容纳应用程序在任何给定时间使用的所有活动数据,再加上一些松弛空间(10%到20%或更多)。

在前面提到的老年代约束条件下:给予年轻代大量内存。随着处理器数量的增加,增加年轻代大小,因为分配可以并行化。

以下是您提供的内容的整体翻译:

5 可用的垃圾收集器

到目前为止的讨论都是关于串行收集器的。Java HotSpot VM包括三种不同类型的收集器,每种都具有不同的性能特征。

串行收集器

串行收集器使用单个线程执行所有垃圾收集工作,这使得它相对高效,因为线程之间没有通信开销。

它最适合单处理器机器,因为它无法利用多处理器硬件,尽管它对于在多处理器上运行的小型数据集(大约100MB左右)的应用程序也可能是有用的。在某些硬件和操作系统配置上,默认选择串行收集器,或者可以使用选项-XX:+UseSerialGC显式启用。

并行收集器(Paralle Collector)

并行收集器也称为吞吐量收集器(throughput collector),它是一种与串行收集器类似的分代收集器。串行和并行收集器之间的主要区别在于,并行收集器有多个线程用于加速垃圾收集。

并行收集器适用于在多处理器或多线程硬件上运行的中等大小到大型数据集的应用程序。可以通过使用-XX:+UseParallelGC选项启用它。

并行压缩是一个功能,它使并行收集器能够并行执行主要收集。没有并行压缩的情况下,主要收集使用单个线程执行,这可能会显著限制可扩展性。如果指定了选项-XX:+UseParallelGC,则默认启用并行压缩。可以通过使用-XX:-UseParallelOldGC选项禁用它。

垃圾优先(G1 means Garbage first)垃圾收集器

G1是一种大多数时间并发的收集器。大多数时间并发的收集器与应用程序并发执行一些昂贵的工作。这种收集器旨在从小机器扩展到具有大量内存的大型多处理器机器。它提供了以高概率满足暂停时间目标的能力,同时实现高吞吐量。

G1在大多数硬件和操作系统配置上默认被选择,或者可以使用-XX:+UseG1GC显式启用。

Z垃圾收集器

Z垃圾收集器(ZGC)是一种可扩展的低延迟垃圾收集器。ZGC执行所有昂贵的工作并发进行,不停止应用程序线程的执行。

ZGC提供的最大暂停时间为几毫秒,但代价是牺牲一些吞吐量。它适用于需要低延迟的应用程序。暂停时间与使用的堆大小无关。ZGC支持从8MB到16TB的堆大小。要启用它,请使用-XX:+UseZGC选项。

选择收集器

除非您的应用程序有相当严格的暂停时间要求,否则首先运行您的应用程序,并允许VM选择收集器。

如果需要,调整堆大小以提高性能。如果性能仍然不符合您的目标,那么使用以下指南作为选择收集器的起点:

如果应用程序的数据集很小(大约100MB左右),那么选择串行收集器,使用选项-XX:+UseSerialGC。

如果应用程序将在单处理器上运行,并且没有暂停时间要求,那么选择串行收集器,使用选项-XX:+UseSerialGC。

如果(a)峰值应用程序性能是首要考虑因素,并且(b)没有暂停时间要求,或者可以接受一秒钟或更长的暂停时间,那么让VM选择收集器,或者选择并行收集器,使用-XX:+UseParallelGC。

如果响应时间比整体吞吐量更重要,并且必须保持较短的垃圾收集暂停时间,那么选择大多数时间并发收集器,使用-XX:+UseG1GC。

如果响应时间是高优先级,那么选择完全并发收集器,使用-XX:UseZGC。

这些指南仅提供了选择收集器的起点,因为性能取决于堆的大小、应用程序维护的活动数据量以及可用处理器的数量和速度。

如果推荐的收集器没有达到期望的性能,那么首先尝试调整堆和代的大小以满足期望的目标。如果性能仍然不足,那么尝试使用不同的收集器:使用并发收集器减少暂停时间,并使用并行收集器在多处理器硬件上增加整体吞吐量。

以下是文档中提到的主要观点汇总:

其他考虑因素

本节涉及影响垃圾收集的其他情况。

终结化(Finalization)和弱引用、软引用、幻象引用

  • 某些应用程序通过使用终结化和弱引用、软引用或幻象引用与垃圾收集交互。
  • 终结化的使用被不推荐,因为它可能导致安全、性能和可靠性问题。
  • 终结化已在JDK 9中被弃用,并计划在JDK 18中移除。
  • 替代终结化的技术包括try-with-Resources语句和Cleaner API。

显式垃圾收集

  • 应用程序可以通过调用System.gc()来显式触发垃圾收集。
  • 显式垃圾收集可能会在不必要的时候强制执行主要收集,因此通常应避免使用。
  • 可以通过设置-XX:+DisableExplicitGC标志来禁用显式垃圾收集,以测量其性能影响。

软引用

  • 软引用在服务器虚拟机中的存活时间比在客户端虚拟机中长。
  • 可以通过-XX:SoftRefLRUPolicyMSPerMB参数控制软引用的清除速率。

类元数据

Java类在Java HotSpot虚拟机内部有表示形式,称为类元数据。

在以前的Java HotSpot虚拟机版本中,类元数据是分配在所谓的永久代中。从JDK 8开始,永久代被移除,类元数据被分配在本地内存中。默认情况下,用于类元数据的本地内存量是没有限制的。可以使用选项-XX:MaxMetaspaceSize对用于类元数据的本地内存量设置上限。

Java HotSpot虚拟机显式管理用于元数据的空间。空间从操作系统请求后被分割成块。类加载器从其块中为元数据分配空间(一个块绑定到一个特定的类加载器)。当类加载器卸载类时,其块会被回收重用或返回给操作系统。元数据使用的是mmap分配的空间,而不是malloc分配的。

[参考]

https://docs.oracle.com/en/java/javase/18/gctuning/introduction-garbage-collection-tuning.html#GUID-326EB4CF-8C8C-4267-8355-21AB04F0D304

相关推荐

B站收藏视频失效?mybili 收藏夹备份神器完整部署指南

本内容来源于@什么值得买APP,观点仅代表作者本人|作者:羊刀仙很多B站用户都有过类似经历:自己精心收藏的视频突然“消失”,点开一看不是“已被删除”,就是“因UP主设置不可见”。而B站并不会主动通知...

中间件推荐初始化配置

Redis推荐初始化配置bind0.0.0.0protected-modeyesport6379tcp-backlog511timeout300tcp-keepalive300...

Redis中缓存穿透问题与解决方法

缓存穿透问题概述在Redis作为缓存使用时,缓存穿透是常见问题。正常查询流程是先从Redis缓存获取数据,若有则直接使用;若没有则去数据库查询,查到后存入缓存。但当请求的数据在缓存和数据库中都...

后端开发必看!Redis 哨兵机制如何保障系统高可用?

你是否曾在项目中遇到过Redis主服务器突然宕机,导致整个业务系统出现数据读取异常、响应延迟甚至服务中断的情况?面对这样的突发状况,作为互联网大厂的后端开发人员,如何快速恢复服务、保障系统的高可用...

Redis合集-大Key处理建议

以下是Redis大Key问题的全流程解决方案,涵盖检测、处理、优化及预防策略,结合代码示例和最佳实践:一、大Key的定义与风险1.大Key判定标准数据类型大Key阈值风险场景S...

深入解析跳跃表:Redis里的&quot;老六&quot;数据结构,专治各种不服

大家好,我是你们的码农段子手,今天要给大家讲一个Redis世界里最会"跳科目三"的数据结构——跳跃表(SkipList)。这货表面上是个青铜,实际上是个王者,连红黑树见了都要喊声大哥。...

Redis 中 AOF 持久化技术原理全解析,看完你就懂了!

你在使用Redis的过程中,有没有担心过数据丢失的问题?尤其是在服务器突然宕机、意外断电等情况发生时,那些还没来得及持久化的数据,是不是让你夜不能寐?别担心,Redis的AOF持久化技术就是...

Redis合集-必备的几款运维工具

Redis在应用Redis时,经常会面临的运维工作,包括Redis的运行状态监控,数据迁移,主从集群、切片集群的部署和运维。接下来,从这三个方面,介绍一些工具。先来学习下监控Redis实时...

别再纠结线程池大小 + 线程数量了,没有固定公式的!

我们在百度上能很轻易地搜索到以下线程池设置大小的理论:在一台服务器上我们按照以下设置CPU密集型的程序-核心数+1I/O密集型的程序-核心数*2你不会真的按照这个理论来设置线程池的...

网络编程—IO多路复用详解

假如你想了解IO多路复用,那本文或许可以帮助你本文的最大目的就是想要把select、epoll在执行过程中干了什么叙述出来,所以具体的代码不会涉及,毕竟不同语言的接口有所区别。基础知识IO多路复用涉及...

5分钟学会C/C++多线程编程进程和线程

前言对线程有基本的理解简单的C++面向过程编程能力创造单个简单的线程。创造单个带参数的线程。如何等待线程结束。创造多个线程,并使用互斥量来防止资源抢占。会使用之后,直接跳到“汇总”,复制模板来用就行...

尽情阅读,技术进阶,详解mmap的原理

1.一句话概括mmapmmap的作用,在应用这一层,是让你把文件的某一段,当作内存一样来访问。将文件映射到物理内存,将进程虚拟空间映射到那块内存。这样,进程不仅能像访问内存一样读写文件,多个进程...

C++11多线程知识点总结

一、多线程的基本概念1、进程与线程的区别和联系进程:进程是一个动态的过程,是一个活动的实体。简单来说,一个应用程序的运行就可以被看做是一个进程;线程:是运行中的实际的任务执行者。可以说,进程中包含了多...

微服务高可用的2个关键技巧,你一定用得上

概述上一篇文章讲了一个朋友公司使用SpringCloud架构遇到问题的一个真实案例,虽然不是什么大的技术问题,但如果对一些东西理解的不深刻,还真会犯一些错误。这篇文章我们来聊聊在微服务架构中,到底如...

Java线程间如何共享与传递数据

1、背景在日常SpringBoot应用或者Java应用开发中,使用多线程编程有很多好处,比如可以同时处理多个任务,提高程序的并发性;可以充分利用计算机的多核处理器,使得程序能够更好地利用计算机的资源,...

取消回复欢迎 发表评论: