为什么有了StringBuffer还会有StringBuilder?

25 阅读2分钟

我们先来看看String,StringBuilder,StringBuffer的区别

1、String 类表示不可变的字符序列。一旦创建了一个字符串,它的值就不能被改变。每次对字符串进行修改时,都会创建一个新的字符串对象,这可能会导致内存开销和性能问题。适用于存储不需要频繁修改的字符串。

2、StringBuilder 类用于创建和操作可变的字符序列。它的主要优点是在进行字符串拼接或修改操作时,不会像 String 那样创建新的对象,而是直接在原始对象上进行修改,因此性能较好。适用于需要频繁进行字符串修改的情况。

3、StringBuffer 与 StringBuilder 类似,也是用于创建和操作可变的字符序列。不同的是,StringBuffer 是线程安全的,即多个线程可以同时访问和修改同一个 StringBuffer 对象而不会导致数据不一致的问题。这种线程安全性是通过在每个方法上添加同步锁来实现的。因此,在需要在多线程环境下进行字符串操作时,需要考虑使用 StringBuffer。

既然StringBuffer 与 StringBuilder 类似,也是用于创建和操作可变的字符序列,而且是线程安全的,那么问题来了,为什么有了StringBuffer还会有StringBuilder?原来是从性能或者说是运行速度方面来考虑的,三者的运行速度快慢为:StringBuilder > StringBuffer > String。

运行速度快慢的原因:

1、String为字符串常量,而StringBuilder和StringBuffer均为字符串变量,即String对象一旦创建之后该对象是不可更改的,但后两者的对象是变量,是可以更改的,对变量进行操作就是直接对该对象进行更改,而不进行创建和回收的操作,所以速度要比String快很多。

2、StringBuilder与 StringBuffer的方法都会调用AbstractStringBuilder中的公共方法,如super.append(…)。只是StringBuffer会在方法上加synchronized关键字,进行同步。 正是synchronized关键字导致运行速度慢的,synchronized 是 JVM 的内置锁,基于 Monitor 机制实现。每一个对象都有一个与之关联的监视器 (Monitor),这个监视器充当了一种互斥锁的角色。当一个线程想要访问某个对象的 synchronized 代码块,首先需要获取该对象的 Monitor。如果该 Monitor 已经被其他线程持有,则当前线程将会被阻塞,直至 Monitor 变为可用状态。当线程完成 synchronized 块的代码执行后,它会释放 Monitor,并把 Monitor 返还给对象池,这样其他线程才能获取 Monitor 并进入 synchronized 代码块。同时synchronized关键字,会对同步的代码先写到工作内存,这样保证了同步,但运行速度也变慢了。