java垃圾回收机制
jvm的gc原理

jvm的gc原理JVM的GC原理一、概述JVM(Java虚拟机)是Java程序运行的环境,其中最重要的组成部分之一就是垃圾回收(Garbage Collection,简称GC)机制。
GC的作用是自动管理程序中的内存,及时释放不再使用的对象,以避免内存泄漏和内存溢出的问题。
本文将对JVM的GC原理进行详细介绍。
二、垃圾回收算法1. 标记-清除算法标记-清除算法是最基本的垃圾回收算法之一。
它的过程分为两个阶段:标记阶段和清除阶段。
在标记阶段,GC会从根节点(一般是程序中的静态变量和栈中的引用)开始,递归地遍历对象图,标记出所有被引用的对象。
在清除阶段,GC会遍历整个堆,清除所有未被标记的对象。
2. 复制算法复制算法是针对标记-清除算法的改进。
它将堆分为两个区域,每次只使用其中一个区域。
当一个区域的对象被标记后,将其复制到另一个区域中,然后清除原来的区域。
这样可以解决碎片问题,但是需要额外的空间来存储复制的对象。
3. 标记-整理算法标记-整理算法是对标记-清除算法的改进。
它的过程与标记-清除算法类似,但是在清除阶段,标记-整理算法会将存活的对象向一端移动,然后清除边界外的所有对象。
这样可以解决碎片问题,并且不需要额外的空间。
4. 分代算法分代算法是针对对象的生命周期不同而提出的。
一般来说,对象的生命周期可以分为年轻代和老年代。
年轻代中的对象生命周期较短,老年代中的对象生命周期较长。
分代算法将堆分为年轻代和老年代两个区域,分别采用不同的垃圾回收算法。
年轻代一般使用复制算法,老年代一般使用标记-清除算法或标记-整理算法。
三、GC的执行过程1. 初始标记初始标记阶段是GC的第一步,它的目的是标记出所有的根对象,并且停止所有的应用线程。
这个过程是短暂的,因为只需要标记出与根对象直接关联的对象。
2. 并发标记并发标记阶段是GC的核心步骤,它的目的是通过并发执行来标记出所有的存活对象。
在这个阶段,GC会遍历整个堆,标记出与根对象直接或间接关联的存活对象。
javaGC垃圾回收机制G1、CMS

javaGC垃圾回收机制G1、CMSCMS(Concurrent Mark-Sweep)是以牺牲吞吐量为代价来获得最短回收停顿时间。
对于要求服务器响应速度的应⽤上,这种垃圾回收器⾮常适合。
在启动JVM参数加上-XX:+UseConcMarkSweepGC ,这个参数表⽰对于⽼年代的回收采⽤CMS。
CMS采⽤的基础算法是:标记—清除。
使⽤场景:1、应⽤程序对停顿⽐较敏感,并且在应⽤程序运⾏的时候可以提供更⼤的内存和更多的CPU2、在JVM中,有相对较多存活时间较长的对象(⽼年代⽐较⼤)会更适合使⽤CMS。
为解决CMS算法产⽣空间碎⽚和其它⼀系列的问题缺陷,HotSpot提供了另外⼀种垃圾回收策略,G1(Garbage First)算法,通过参数-XX:+UseG1GC来启⽤,该算法在JDK 7u4版本被正式推出,G1垃圾收集算法主要应⽤在多CPU⼤内存的服务中,在满⾜⾼吞吐量的同时,竟可能的满⾜垃圾回收时的暂停时间,下⾯是官⽅介绍:The Garbage-First (G1) collector is a server-style garbage collector, targeted for multi-processor machines with large memories.It meets garbage collection (GC) pause time goals with a high probability, while achieving high throughput. The G1 garbagecollector is fully supported in Oracle JDK 7 update 4 and later releases. The G1 collector is designed for applications that:Can operate concurrently with applications threads like the CMS collector.Compact free space without lengthy GC induced pause times.Need more predictable GC pause durations.Do not want to sacrifice a lot of throughput performance.Do not require a much larger Java heap.G1采⽤了另外⼀种完全不同的⽅式组织堆内存,堆内存被划分为多个⼤⼩相等的内存块(Region),每个Region是逻辑连续的⼀段内存,G1中提供了三种模式垃圾回收模式,young gc、mixed gc 和 full gc,在不同的条件下被触发。
java自动垃圾回收机制

java⾃动垃圾回收机制前⾔:相⽐C++,java做的⼀⼤改进是将复杂的内存管理抽离出来交给jvm去处理,让码农不再时刻盯着内存泄漏的问题,可以更专注于业务逻辑的开发。
java的GC机制是和其内存模型相关联的,⽽GC的核⼼内存区域是内存中的堆区。
java堆区按对象的存活时间被分为了年轻代(eden区+s0区+s1区)和⽼年代(tentired区),java堆的按代区分其实是为了其垃圾回收的分代收集机制打开了⽅便之门。
java的GC收集器会在不同的分代上使⽤不同的垃圾收集策略。
GC其实主要需要解决两个问题:哪些是垃圾?如何清理垃圾?在解决这两个问题上涉及到下⾯的⽅法论:1.垃圾对象判定⽅法引⽤计数法:在C++的智能指针中使⽤了这种⽅式去做内存的⾃动回收。
即在对象⽣成时维护⼀个对该对象引⽤次数的计数器,对象初次⽣成时计数器值为1,每增加⼀个到该对象的引⽤,计数器加1,每减少⼀个引⽤(如引⽤变量赋值null,或引⽤变量离开作⽤域),计数器减1,计数器为零时,对象内存会被⾃动回收。
该⽅法的问题是存在内存泄漏的隐患,如对象相互引⽤、循环引⽤等情况相互引⽤:public class ReferenceCountingGc {Object instance = null;public static void main(String[] args) {ReferenceCountingGc objA = new ReferenceCountingGc();ReferenceCountingGc objB = new ReferenceCountingGc();objA.instance = objB;objB.instance = objA;objA = null;objB = null;}} 例⼦中两个new出来的对象ReferenceCountingGc由于通过内部的变量instance引⽤着对⽅,两个对象的引⽤计数都为1。
finalize机制

finalize机制【最新版】目录1.Finalize 机制的概述2.Finalize 机制的作用3.Finalize 机制的实现原理4.Finalize 机制的实例应用5.Finalize 机制的优缺点正文【1.Finalize 机制的概述】Finalize 机制,是 Java 语言中一种用于确保对象在垃圾回收之前执行一定操作的机制。
它允许对象在特定的时刻进行一些必要的清理工作,以确保对象被正确地回收。
【2.Finalize 机制的作用】Finalize 机制的主要作用有两点:(1)对象的自我清理:在垃圾回收之前,对象可以利用 Finalize 机制执行一些清理工作,如关闭文件、断开网络连接等。
这样可以确保对象被正确地回收,避免资源泄露。
(2)延长对象的生存时间:如果对象在 Finalize 方法中执行了一些操作,那么垃圾回收器会考虑这些操作,从而延长对象的生存时间。
这对于某些需要在特定时刻执行操作的对象非常有用。
【3.Finalize 机制的实现原理】Finalize 机制的实现原理主要基于 Java 的垃圾回收机制。
当垃圾回收器决定回收一个对象时,它会首先调用对象的 Finalize 方法。
如果对象实现了 Finalize 方法,那么它会在方法中执行相应的清理操作。
然后,垃圾回收器会再次检查对象,如果对象已经完成了清理工作,那么它就会被回收。
否则,对象会被移至下一次垃圾回收。
【4.Finalize 机制的实例应用】以下是一个 Finalize 机制的实例应用:```javaclass Example {private File file;public Example(String fileName) {file = new File(fileName);}public void write(String content) {try {file.write(content);} catch (IOException e) {e.printStackTrace();}}protected void finalize() {try {file.close();} catch (IOException e) {e.printStackTrace();}}}```在这个例子中,我们创建了一个名为 Example 的类。
javagc回收机制

javagc回收机制即java垃圾回收机制,是自动的内存管理机制,它可以在程序执行时自动回收无用的对象,以释放内存空间。
Java 中的垃圾回收机制主要包括以下几个方面:
1. 对象的创建和销毁:当一个对象被创建时,Java 虚拟机会为其分配一块内存空间,并记录其在内存中的位置。
当对象不再被引用时,Java 虚拟机会将其标记为垃圾对象,并在适当的时候回收它所占用的内存空间。
2. 垃圾收集算法:Java 中使用的垃圾收集算法主要有标记-清除算法和复制算法。
标记-清除算法会先标记所有还在使用中的对象,然后清除所有未被标记的对象;复制算法则会将内存分为两个区域,将还在使用中的对象复制到其中一个区域,然后清除另一个区域中的所有对象。
3. 垃圾收集器的选择和配置:Java 中提供了多种垃圾收集器,如Serial GC、Parallel GC、CMS GC 等。
可以根据程序的特点和运行环境的需求选择合适的垃圾收集器和配置参数,以达到最优的垃圾回收效果。
4. 垃圾回收的影响:垃圾回收会占用一定的系统资源,可能会影响程序的性能。
因此,在进行垃圾回收时需要注意控制回收的频率和时间,以避免对程序的性能造成过大的影响。
总的来说,Java 中的垃圾回收机制是一个自动化的、高效的内存管理机制,可以帮助开发人员避免内存泄漏等问题,提高程序的稳定性和可靠性。
java中stack和heap的区别,java中的垃圾回收机制

java中stack和heap的区别,java中的垃圾回收机制#. 在java中有两类内存。
分别称为stack(栈)和heap(堆)。
stack是程序内存空间,因此所有的基本类型和对象的引⽤是存在stack中。
heap是java虚拟机储存对象的,它是⼀个巨⼤的内存,当你创造⼀个对象,java虚拟机把对象放⼊heap中,把创造的对象的地址放⼊stack中。
因此,基本类型、对象的引⽤储存在stack中;对象储存在heap中。
#. java中的垃圾回收机制
当你new⼀个新的对象,java分配必需的内存。
当你⽤完⼀个对象时,java的垃圾回收器为你把内存收回。
垃圾回收以线程的形式在后台运⾏,寻找那些⽆有⽤引⽤(reference)的对象,发现之后便销毁对象,并收回内存。
垃圾回收是在java虚拟机间实现的,它们通常有相同的步骤,⾸先垃圾回收器获得正在运⾏的线程和所有已经加载的类的快照,
然后所有线程中涉及到的对象被标记为最近使⽤的,当可能涉及的对象都被标记的时候,剩下没标记的就被舍弃。
为了帮助虚拟机,我们主动移除⼀些不在需要的对象是⼀个不错的做法,可以通过将引⽤设置为null来实现。
eg:
Text t = new Test();
t.someAction();
//all done
t = null;。
JVM垃圾回收算法及G1回收机制

JVM垃圾回收算法及G1回收机制JVM(Java Virtual Machine)是Java程序运行的环境,其中的垃圾回收算法是JVM内存管理的重要组成部分。
垃圾回收算法的作用是自动释放不再使用的内存空间,以提高程序的性能和效率。
其中,G1(Garbage-First)是一种现代化的垃圾回收器,相较于传统的垃圾回收算法具有更高的效率和更低的延迟。
垃圾回收算法的核心思想是通过扫描内存,找出不再被引用的对象,并将其释放。
常见的垃圾回收算法包括标记-清除算法、复制算法、标记-整理算法等。
标记-清除算法是最基础的垃圾回收算法之一、它通过标记所有被引用的对象,然后清除未被标记的对象。
这个算法的优点是可以处理任意的内存分配情况,但是会产生大量的碎片化空间。
复制算法是另一种常见的垃圾回收算法。
它将内存分为两个区域,每次只使用其中一个区域。
当一个区域满了之后,将还存活的对象复制到另一个区域,然后清除当前区域。
这个算法的优点是简单高效,但是会浪费一半的内存空间。
标记-整理算法是标记-清除算法的改进版。
它先标记所有被引用的对象,然后将存活的对象向一端移动,然后清除边界之外的对象。
这个算法的优点是可以减少碎片化空间,但是会有对象移动的开销。
G1是一种基于标记-整理算法的垃圾回收器,它在Java SE 6u14版本中引入。
G1回收机制主要有以下几个特点:首先,G1将堆内存划分为若干个大小相等的区域(Region),每个区域可以是Eden区、Survivor区或Old区。
这种划分方式可以有效地减少碎片化问题,并且可以根据实际情况动态调整区域的大小。
其次,G1采用了增量式的标记算法,在应用程序运行的同时进行垃圾回收操作。
这样可以减少单次垃圾回收的暂停时间,并且将垃圾回收的工作均匀地分布在多个时间片段中,避免长时间的停顿。
再次,G1使用了全局的标记-整理算法。
它通过标记所有被引用的对象,然后将存活的对象向一端移动,并清除边界之外的对象。
Java8的GC垃圾回收

Java8的GC垃圾回收Java垃圾回收概况Java GC(Garbage Collection,垃圾回收)机制,是Java与C++/C的主要区别之⼀,作为Java开发者,⼀般不需要专门编写内存回收和垃圾清理代码,对内存泄露和溢出的问题,也不需要像C程序员那样战战兢兢。
这是因为在Java虚拟机中,存在⾃动内存管理和垃圾清扫机制。
概括地说,该机制对JVM中的内存进⾏标记,并确定哪些内存需要回收,根据⼀定的回收策略,⾃动的回收内存,永不停息的保证JVM 中的内存空间,防⽌出现内存泄露和溢出问题。
关于JVM,需要说明⼀下的是,⽬前使⽤最多的Sun公司的JDK中,⾃从1999年的JDK1.2开始直⾄现在仍在⼴泛使⽤的JDK6,其中默认的虚拟机都是HotSpot。
2009年,Oracle收购Sun,加上之前收购的EBA公司,Oracle拥有3⼤虚拟机中的两个:JRockit和HotSpot,Oracle也表明了想要整合两⼤虚拟机的意图,但是⽬前在新发布的JDK8中,默认的虚拟机仍然是HotSpot,因此本⽂中默认介绍的虚拟机都是HotSpot,相关机制也主要是指HotSpot的GC机制。
Java GC机制主要完成3件事:确定哪些内存需要回收确定什么时候需要执⾏GC如何执⾏GC经过这么长时间的发展,Java GC机制已经⽇臻完善,⼏乎可以⾃动的为我们做绝⼤多数的事情。
然⽽,如果我们从事较⼤型的应⽤软件开发,曾经出现过内存优化的需求,就必定要研究Java GC机制。
学习Java GC机制,可以帮助我们在⽇常⼯作中排查各种内存溢出或泄露问题,解决性能瓶颈,达到更⾼的并发量,写出更⾼效的程序。
我们将从4个⽅⾯学习Java GC机制,1,内存是如何分配的;2,如何保证内存不被错误回收(即:哪些内存需要回收);3,在什么情况下执⾏GC以及执⾏GC的⽅式;4,如何监控和优化GC机制。
内存是如何分配的这⾥所说的内存分配,主要指的是在堆上的分配,⼀般的,对象的内存分配都是在堆上进⾏,但现代技术也⽀持将对象拆成标量类型(标量类型即原⼦类型,表⽰单个值,可以是基本类型或String等),然后在栈上分配,在栈上分配的很少见,我们这⾥不考虑,接下来我们⼀起来了解下内存分区,对我们后⾯学习的有所帮助。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
上次讲到引用类型和基本类型由于内存分配上的差异导致的性能问题。
那么今天就来聊一下和内存释放(主要是gc)有关的话题。
事先声明一下:虽说sun公司已经被oracle吞并了,但是出于习惯,同时也为了偷懒节省打字,以下仍然称之为sun公司。
★jvm的内存在java虚拟机规范中(具体章节请看“这里”),提及了如下几种类型的内存空间:◇栈内存(stack):每个线程私有的。
◇堆内存(heap):所有线程公用的。
◇方法区(method area):有点像以前常说的“进程代码段”,这里面存放了每个加载类的反射信息、类函数的代码、编译时常量等信息。
◇原生方法栈(native method stack):主要用于jni中的原生代码,平时很少涉及。
关于栈内存(stack)和堆内存(heap),已经在上次的帖子中扫盲过了,大伙儿应该有点印象。
由于今天咱们要讨论的“垃圾回收”话题,主要是和堆内存(heap)有关。
其它的几个玩意儿不是今天讨论的重点。
等以后有空了,或许可以单独聊一下。
★垃圾回收机制简介其实java虚拟机规范中并未规定垃圾回收的相关细节。
垃圾回收具体该怎么搞,完全取决于各个jvm的设计者。
所以,不同的jvm之间,gc的行为可能会有一定的差异。
下面咱拿sun官方的jvm来简单介绍一下gc的机制。
◇啥时候进行垃圾回收?一般情况下,当jvm发现堆内存比较紧张、不太够用时,它就会着手进行垃圾回收工作。
但是大伙儿要认清这样一个残酷的事实:jvm进行gc的时间点是无法准确预知的。
因为gc启动的时刻会受到各种运行环境因素的影响,随机性太大。
虽说咱们无法准确预知,但如果你想知道每次垃圾回收执行的情况,还是蛮方便的。
可以通过jvm的命令行参数“-xx:+printgc”把相关信息打印出来。
另外,调用system.gc()只是建议jvm进行gc。
至于jvm到底会不会做,那就不好说啦。
通常不建议自己手动调用system.gc(),还是让jvm自行决定比较好。
另外,使用jvm命令行参数“-xx:+disableexplicitgc”可以让system.gc()不起作用。
◇谁来负责垃圾回收?一般情况下,jvm会有一个或多个专门的垃圾回收线程,由它们负责清理回收垃圾内存。
◇如何发现垃圾对象?垃圾回收线程会从“根集(root set)”开始进行对象引用的遍历。
所谓的“根集”,就是正在运行的线程中,可以访问的引用变量的集合(比如所有线程当前函数的参数和局部变量、当前类的成员变量等等)。
垃圾回收线程先找出被根集直接引用的所有对象(不妨叫集合1),然后再找出被集合1直接引用的所有对象(不妨叫集合2),然后再找出被集合2直接引用的所有对象......如此循环往复,直到把能遍历到的对象都遍历完。
凡是从根集通过上述遍历可以到达的对象,都称为可达对象或有效对象;反之,则是不可达对象或失效对象(也就是垃圾)。
◇如何清理/回收垃圾?通过上述阶段,就把垃圾对象都找出来。
然后垃圾回收线程会进行相应的清理和回收工作,包括:把垃圾内存重新变为可用内存、进行内存的整理以消除内存碎片、等等。
这个过程会涉及到若干算法,有兴趣的同学可以参见“这里”。
限于篇幅,咱就不深入聊了。
◇分代早期的jvm是不采用分代技术的,所有被gc管理的对象都存放在同一个堆里面。
这么做的缺点比较明显:每次进行gc都要遍历所有对象,开销很大。
其实大部分的对象生命周期都很短(短命对象),只有少数对象比较长寿;在这些短命对象中,又只有少数对象占用的内存空间大;其它大量的短命对象都属于小对象(很符合二八原理)。
有鉴于此,从jdk 1.2之后,jvm开始使用分代的垃圾回收(generational garbage collection)。
jvm把gc相关的内存分为年老代(tenured)和年轻代(nursery)、持久代(permanent,对应于jvm规范的方法区)。
大部分对象在刚创建时,都位于年轻代。
如果某对象经历了几轮gc还活着(大龄对象),就把它移到年老代。
另外,如果某个对象在创建时比较大,可能就直接被丢到年老代。
经过这种策略,使得年轻代总是保存那些短命的小对象。
在空间尺寸上,年轻代相对较小,而年老代相对较大。
因为有了分代技术,jvm的gc也相应分为两种:主要收集(major collection)和次要收集(minor collection)。
主要收集同时清理年老代和年轻代,因此开销很大,不常进行;次要收集仅仅清理年轻代,开销很小,经常进行。
★gc对性能会有啥影响?刚才介绍了gc的大致原理,那gc对性能会造成哪些影响捏?主要有如下几个方面:◇造成当前运行线程的停顿早期的gc比较弱智。
在它工作期间,所有其它的线程都被暂停(以免影响垃圾回收工作)。
等到gc干完活,其它线程再继续运行。
所以,早期jdk的gc一旦开始工作,整个程序就会陷入假死状态,失去各种响应。
经过这些年的技术改进(包括采用分代技术),从jdk 1.4开始,gc已经比较精明了。
在它干活期间,只是偶尔暂停一下其它线程的运行(从长时间假死变为暂时性休克)。
◇遍历对象引用的开销试想如果jvm中的对象很多,那遍历完所有可达对象肯定是比较费劲的工作,这个开销可不小。
◇清理和回收垃圾的开销遍历完对象引用之后,对垃圾的清理和回收也有较大的开销。
这部分开销可能包括复制内存块、更新对象引用等等。
★几种收集器◇两个性能指标因为今天聊的是性能的话题,必然会提到衡量gc性能的两个重要指标:吞吐量(throughput)和停顿时间(pause time)。
吞吐量这个词不是很直观,解释一下:就是jvm不用于gc的时间占总时间的比率。
吞吐量是越大越好,停顿时间是越小越好。
不同的应用程序对这两个指标的关注点不一样(后面具体会说),也就是所谓的“众口难调”。
很多jvm厂商为了迎合“众口”,不得不提供多种几种垃圾收集器供使用者选择。
不同的收集器,采用的收集策略是不一样的,下面具体介绍。
◇串行收集器(serial collector)使用命令行选项“-xx:+useserialgc”指定。
这种收集器是最传统的收集器。
它使用单线程进行垃圾回收,对于单cpu机器比较合适。
另外,小型应用或者对上述两个指标没有特殊要求的,可以使用串行收集器。
◇并行收集器(parallel throughput collector)顾名思义,这种收集器使用多个线程进行垃圾回收以达到高吞吐量。
垃圾回收线程的数量通过命令行选项“-xx:parallelgcthreads=n”指定。
可以设置该数值以便充分利用多cpu/多核。
当使用命令行选项“-xx:+useparallelgc”时:它会针对年轻代使用多个垃圾回收线程,对年老代依然使用单个线程的串行方式。
此选项最早在jdk 1.5引入。
当使用命令行选项“-xx:+useparalleloldgc”时:它针对年轻代和年老代都使用多个垃圾回收线程的方式。
不过此选项从jdk 1.6才开始引入。
◇并发收集器(concurrent low pause collector)使用命令行选项“-xx:+useconcmarksweepgc”指定。
这种收集器优先保证程序的响应。
它会尽量让垃圾回收线程和应用自身的线程同时运行,从而降低停顿时间。
此选项从jdk 1.4.1开始支持。
◇增量收集器(incremental collector)自从jdk 1.4.2以来,sun官方就停止维护该收集器了。
所以俺就节省点口水,不多说了。
★如何降低gc的影响?◇尽量减少堆内存的使用由于gc是针对存储在堆内存的对象进行的。
咱们如果在程序中减少引用对象的分配(也就相应降低堆内存分配),那对于提高gc的性能是很有帮助滴。
上次“字符串过滤实战”的帖子给出了一个例子,示范了如何通过降低堆内存的分配次数来提升性能。
◇设置合适的堆内存大小jvm的堆内存是有讲究的,不能太大也不能太小。
如果堆内存太小,jvm老是感觉内存不够用,可能会导致频繁进行垃圾回收,影响了性能;如果堆内存太大,以至于操作系统的大部分物理内存都被jvm自个儿霸占了,那可能会影响其它应用程序甚至操作系统本身的性能。
另外,年轻代的大小(或者说年轻代与年老代的比值)对于gc的性能也有明显影响。
如果年轻代太小,可能导致次要收集很频繁;如果年轻代太大,导致次要收集的停顿很明显。
jvm提供了若干和堆内存大小相关的命令行选项,具体如下:-------------------------------xms设置初始堆内存-xmx设置最大堆内存-xmn设置年轻代的大小-xx:newratio=n设置年轻代与年老代的比例为“n”-xx:newsize=n设置年轻代大小为“n”------------------------------一般情况下,jvm的默认参数值已经够用。
所以没事儿别轻易动用上述选项。
如果你非调整不可,一定要做深入的性能对比测试,保证调整后的性能确实优于默认参数值。
◇吞吐量和停顿的取舍前面提到了不同应用的众口难调。
常见的口味有两种:(1)看重吞吐量,对停顿时间无所谓;(2)侧重于停顿时间。
对于某些在后台的、单纯运算密集型的应用,属于第一种。
比如某些科学计算的应用。
这时候建议使用并行收集器。
对于涉及用户ui交互的、实时性要求比较高、程序需要快速响应的,属于第二种。
比如某些桌面游戏、某些电信交换系统。
这时候建议使用并发收集器。