总结:
1,不要大量使用不可变对象和不可边对象提供的方法(每次调用不可变对象的修改方法会创建出新的对象出来,导致频繁的YGC)
2,计算密集型任务不要使用包装类(包装类体积大,数据密度低,增加取存数据时间。运算时也会创建大量的包装类对象出来)
3,不要再循环体中使用不可变对象提供的方法(可能会创建大量的一次性对象出来)
一,java中的不可变对象
Java中有许多不可变的对象,以下是其中的一些:
- 字符串(String):字符串在Java中是不可变的对象。一旦创建了一个字符串对象,它的值就不能被修改。
- 整数(Integer)、长整数(Long)、浮点数(Float)和双精度浮点数(Double):这些数字类型在Java中也是不可变的对象。一旦创建了一个数字对象,它的值就不能被修改。
- 枚举(Enum):枚举类型也是不可变的对象。枚举类型中的每个元素都是一个不可变的对象。
- LocalDate、LocalTime、LocalDateTime:Java 8中的日期和时间API中的这些类也是不可变的对象。一旦创建了一个日期或时间对象,它的值就不能被修改。
- BigInteger、BigDecimal:这些类提供了任意精度的整数和浮点数运算,也是不可变的对象。
Java 中的不可变对象(Immutable Objects)详解_immutable object is modified-CSDN博客
二,不可变对象的优点
线程安装,当a、b两个线程使用一个不可变对象时obj时,b线程修改obj值时实际会创建一个新的对象给b使用,这时a、b所持有的实际是不同的对象,互不影响,所有是线程安全的、
三,测试不可变对象LocalDateTime的plusMinutes()方法
1. main 方法
public class test6 {
public static void main(String[] args) throws InterruptedException {
String threadName = Thread.currentThread().getName();
System.out.println("Current Thread Name: " + threadName);
// 获取当前进程PID
RuntimeMXBean runtimeMxBean = ManagementFactory.getRuntimeMXBean();
String processId = runtimeMxBean.getName().split("@")[0];
System.out.println("Current Process ID: " + processId);
Thread.sleep(2000);
LocalDateTime dateTime1 = LocalDateTime.of(2024, 5, 1, 9, 0); // 2024年5月1日 9:00
Double d = 1.0;
double e = 1.0;
while (true){
// e +=1.0;
dateTime1.plusMinutes(1);
}
}
}
2. 运行方法
java -Xms100M -Xmx100M -Xmn50M -cp . test6.java
这里设置设置JVM启动时的堆内存大小、最大堆内存为100M,设置新生代的大小为50M
3 . 查看YGC次数,平均每秒50多次
4,统计heap中的对象数量
注:LocalDateTime对象中包含了LocalTime对象和LocalDate对象
5,源码分析
plusMinutes()->plusWithOverflow()->with()
当this的日期和时间不等时就会创建新的对象出来,
(LocalDateTime的date、time属性由final修饰,不可更改)
6,可用同样的方法测试包装类
虽然java为基本数据类型提供了包装类,但有的情况用包装类真不合适,创建时间长,回收时间长,存取时间长。
当修改为基本数据类型时: