1. Java关键字解释
在Java中,synchronized、volatile和transient是重要的关键字,用于多线程编程和对象序列化。
-
synchronized:
-
这是一个同步关键字,用于控制多线程访问共享资源,防止数据不一致。它可以用在方法或代码块上。
-
当线程进入
synchronized方法或块时,它会获取对象的锁(monitor),其他线程必须等待锁释放后才能访问。 -
示例代码:
public class Counter { private int count = 0; public synchronized void increment() { count++; // 线程安全操作 } } -
优点:简单易用,能保证原子性和可见性。缺点:可能引起性能问题,如死锁或线程阻塞。
-
-
volatile:
-
用于确保变量的可见性(visibility),即当一个线程修改了
volatile变量时,其他线程能立即看到最新值。 -
它不保证原子性(例如,
count++操作不是原子的),但常用于标志位或简单状态变量。 -
示例代码:
public class SharedFlag { private volatile boolean flag = false; public void setFlag(boolean value) { flag = value; // 修改后,其他线程立即可见 } } -
适用场景:轻量级同步,如控制线程启动/停止。注意:复杂操作仍需
synchronized或java.util.concurrent类。
-
-
transient:
-
用于对象序列化(如使用
ObjectOutputStream),标记字段不应被序列化。序列化时,该字段的值会被忽略。 -
常用于敏感数据(如密码)或临时状态,避免不必要的数据传输。
-
示例代码:
import java.io.Serializable; public class User implements Serializable { private String username; private transient String password; // 序列化时跳过password public User(String username, String password) { this.username = username; this.password = password; } } -
反序列化后,
password字段会为null或默认值。
-
2. 常见的GC回收器
垃圾回收(Garbage Collection, GC)是JVM自动管理内存的核心机制。常见的GC回收器针对不同场景优化,以下是主流回收器及其特点:
-
Serial GC:
- 单线程回收器,适用于小型应用或客户端环境(如桌面程序)。
- 工作方式:使用标记-清除(Mark-Sweep)算法,暂停所有应用线程(Stop-The-World)。
- 优点:简单,内存开销小。缺点:停顿时间长,不适合高并发系统。
- 启动参数:
-XX:+UseSerialGC
-
Parallel GC (Throughput Collector):
- 多线程回收器,注重吞吐量(Throughput),适用于后台处理或批处理任务。
- 工作方式:多线程并行执行标记和清除,减少停顿时间。
- 优点:吞吐量高,适合CPU密集型应用。缺点:停顿时间仍较长。
- 启动参数:
-XX:+UseParallelGC
-
Concurrent Mark Sweep (CMS):
- 低停顿回收器,适用于响应时间敏感的应用(如Web服务)。
- 工作方式:并发标记阶段与应用线程并行,减少停顿;清除阶段可能暂停。
- 优点:停顿时间短。缺点:内存碎片问题,可能引起Full GC。
- 启动参数:
-XX:+UseConcMarkSweepGC(在Java 8及之前)
-
Garbage-First (G1):
- 从Java 7引入,适用于大内存和多核系统,目标是平衡吞吐量和停顿时间。
- 工作方式:将堆划分为多个区域(Region),优先回收垃圾最多的区域(Garbage-First)。
- 优点:可预测停顿时间,支持大堆。缺点:配置复杂。
- 启动参数:
-XX:+UseG1GC(Java 9后默认)
-
Z Garbage Collector (ZGC):
- Java 11引入,专注于极低停顿(sub-millisecond),适合大型应用。
- 工作方式:并发标记和清除,使用彩色指针等技术。
- 优点:停顿时间几乎不受堆大小影响。缺点:资源消耗较高。
- 启动参数:
-XX:+UseZGC
-
Shenandoah:
- 类似ZGC,低停顿回收器,支持并发压缩。
- 工作方式:并发执行所有阶段,减少停顿。
- 优点:停顿时间短。缺点:需特定JVM支持(如OpenJDK)。
- 启动参数:
-XX:+UseShenandoahGC
选择回收器时,需考虑应用类型:高吞吐用Parallel,低停顿用G1、ZGC或Shenandoah。
3. JVM调优
JVM调优旨在优化性能、减少GC停顿和内存使用。核心方法包括调整堆大小、选择GC回收器和监控日志。以下是常见调优策略:
-
堆大小设置:
- 初始堆大小(
-Xms)和最大堆大小(-Xmx)应设置为相同值,避免堆动态调整带来的开销。例如:-Xms4g -Xmx4g表示4GB堆。 - 年轻代(Young Generation)大小调整:使用
-XX:NewRatio(老年代与年轻代比例)或-XX:NewSize和-XX:MaxNewSize。 - 建议:根据应用内存需求设置,避免OOM(OutOfMemoryError)。
- 初始堆大小(
-
GC回收器选择:
- 基于应用需求选择回收器(如上所述)。例如,Web服务用G1或ZGC,批处理用Parallel。
- 启动参数示例:
-XX:+UseG1GC -XX:MaxGCPauseMillis=200设置G1最大停顿为200ms。
-
监控与日志:
- 启用GC日志:
-XX:+PrintGCDetails -XX:+PrintGCDateStamps -Xloggc:gc.log - 使用工具分析:JVisualVM、JConsole或GC日志分析器(如GCViewer)来识别瓶颈。
- 关键指标:GC频率、停顿时间、内存使用率。
- 启用GC日志:
-
常见调优参数:
-XX:SurvivorRatio:年轻代中Eden区与Survivor区的比例。-XX:MaxTenuringThreshold:对象晋升老年代的阈值。-XX:+UseStringDeduplication:字符串去重(G1特有)。- 调优原则:从小范围测试开始,逐步优化。
-
避免常见问题:
- 内存泄漏:使用堆转储(
-XX:+HeapDumpOnOutOfMemoryError)分析。 - 频繁GC:检查对象分配模式,优化代码或调整堆大小。
- 停顿过长:切换到低停顿回收器或调整
-XX:MaxGCPauseMillis.
- 内存泄漏:使用堆转储(
调优是迭代过程:先基准测试,再调整参数,监控效果。建议在开发或测试环境进行,避免生产环境风险。