【quill源码分析】【大数运算源码】【iOS收费源码】源码stringbuffer

时间:2024-12-23 06:08:22 编辑:常德桃源码头 来源:java app接口源码

1.stringbuffer与stringbuilder的区别?源码
2.stringbuffer扩容为什么是2倍+2?
3.String,StringBuffer和StringBuilder的区别
4.StringBuilder为什么线程不安全?
5.为什么?为什么StringBuilder是线程不安全的?
6.面试篇==和equals()区别、String线程安全问题(StringBuilder)

源码stringbuffer

stringbuffer与stringbuilder的区别?源码

       äºŒè€…的区别主要是在运行速度和线程安全这两方面。

       1、StringBuffer 与 StringBuilder 中的方法和功能完全是等价的

       2、只是StringBuffer 中的方法大都采用了 synchronized å…³é”®å­—进行修饰,因此是线程安全的,而 StringBuilder 没有这个修饰,可以被认为是线程不安全的。

       3、在单线程程序下,StringBuilder效率更快,因为它不需要加锁,不具备多线程安全而StringBuffer则每次都需要判断锁,效率相对更低。

stringbuffer扩容为什么是2倍+2?

       在常规用法中,StringBuffer和StringBuilder在功能上差别不大,源码主要区别在于StringBuffer具备线程安全性,源码但效率相对较低,源码而StringBuilder则线程不安全但效率更高。源码quill源码分析不过在扩容机制上,源码两者一致。源码下面以StringBuffer为例进行深入分析。源码

       首先,源码追踪StringBuffer源码,源码发现它继承自AbstractStringBuilder。源码这意味着StringBuffer和StringBuilder是源码“亲兄弟”,拥有共同的源码抽象父类AbstractStringBuilder。在这个抽象类中,源码大数运算源码定义了字符串存储的定长字节数组,并在追加字符串时,当长度超过数组长度时,通过数组复制方式实现扩容。

       容量设置上,StringBuffer提供了默认容量和自定义容量的构造方法,即使默认构造方法也会设置初始容量为。在实际开发中,容量不足时,通过append()方法追加字符串触发动态扩容。

       append()方法实际上调用的是AbstractStringBuilder的append()方法,进入内部后,发现关键在于ensureCapacityInternal()方法。该方法确保内部容量足够,iOS收费源码通过count+len参数计算追加后字符串总长度,实现动态扩容。

       在ensureCapacityInternal()方法中,首先利用二进制位右移运算计算数组原有容量,考虑到编码方式(默认Latin1或UTF-),判断新字符串长度是否超过原有容量。若超过,则利用Arrays.copyOf()方法复制并创建新数组,将当前数组值赋给新数组,完成扩容。

       newCapacity()方法计算扩容后数组长度,通常在新字符串长度基础上增加一定比例,确保足够容纳新追加的字符串。而新长度计算逻辑通常涉及Math.max()方法,点钟器源码确保不会超出Integer最大值,避免内存溢出异常。

       StringBuffer扩容机制核心如下:若一次追加字符串长度超过当前容量,扩容规则为当前容量*2+2;如果追加长度超出初始容量且按当前容量*2+2扩容后仍不足,直接扩容至与新字符串长度相等;后续追加继续遵循当前容量*2+2规则。扩容为2倍+2的原因是为了减少内存分配次数和内存碎片,提高性能和效率。

       为了验证上述规则,可设计实验案例,观察StringBuffer与StringBuilder的扩容表现。至此,详细解释了StringBuffer扩容机制及其规则,希望能对理解Java中字符串操作有所帮助。

String,StringBuffer和StringBuilder的区别

       java中String、StringBuffer、StringBuilder是编程中经常使用的字符串类,他们之间的区别也是经常在面试中会问到的问题。现在总结一下,看看他们的不同与相同。

       1.可变与不可变

       ã€€ã€€String类中使用字符数组保存字符串,如下就是,因为有“final”修饰符,所以可以知道string对象是不可变的。

       ã€€ã€€ã€€ã€€private final char value[];

       ã€€ã€€StringBuilder与StringBuffer都继承自AbstractStringBuilder类,在AbstractStringBuilder中也是使用字符数组保存字符串,如下就是,可知这两种对象都是可变的。

       ã€€ã€€ã€€ã€€char[] value;

       2.是否多线程安全

       ã€€ã€€String中的对象是不可变的,也就可以理解为常量,显然线程安全。

       ã€€ã€€AbstractStringBuilder是StringBuilder与StringBuffer的公共父类,定义了一些字符串的基本操作,如expandCapacity、append、insert、indexOf等公共方法。

       ã€€ã€€StringBuffer对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。看如下源码:

1 public synchronized StringBuffer reverse() {

       2     super.reverse();

       3     return this;

       4 }

       5 

       6 public int indexOf(String str) {

       7     return indexOf(str,warring源码分析 0);        //存在 public synchronized int indexOf(String str, int fromIndex) æ–¹æ³•

       8 }

       ã€€ã€€StringBuilder并没有对方法进行加同步锁,所以是非线程安全的。

        3.StringBuilder与StringBuffer共同点

       ã€€ã€€StringBuilder与StringBuffer有公共父类AbstractStringBuilder(抽象类)。

       ã€€ã€€æŠ½è±¡ç±»ä¸ŽæŽ¥å£çš„其中一个区别是:抽象类中可以定义一些子类的公共方法,子类只需要增加新的功能,不需要重复写已经存在的方法;而接口中只是对方法的申明和常量的定义。

       ã€€ã€€StringBuilder、StringBuffer的方法都会调用AbstractStringBuilder中的公共方法,如super.append(...)。只是StringBuffer会在方法上加synchronized关键字,进行同步。

       ã€€ã€€æœ€åŽï¼Œå¦‚果程序不是多线程的,那么使用StringBuilder效率高于StringBuffer。

StringBuilder为什么线程不安全?

       æ ¸å¿ƒæç¤ºï¼šåœ¨å‰é¢çš„面试题讲解中我们对比了String、StringBuilder和StringBuffer的区别,其中一项便提到StringBuilder是非线程安全的,那么是什么原因导致了StringBuilder的线程不安全呢?原因分析如果你看了StringBuilder或StringBuffer的源代码会说,因为StringBuilder在append操作时并未使用线程同步,而StringBuffer几乎大部分方法都使用了synchronized关键字进行方法级别的同步处理。上面这种说法肯定是正确的,对照

       åœ¨å‰é¢çš„面试题讲解中我们对比了String、StringBuilder和StringBuffer的区别,其中一项便提到StringBuilder是非线程安全的,那么是什么原因导致了StringBuilder的线程不安全呢?

       åŽŸå› åˆ†æž

       å¦‚果你看了StringBuilder或StringBuffer的源代码会说,因为StringBuilder在append操作时并未使用线程同步,而StringBuffer几乎大部分方法都使用了synchronized关键字进行方法级别的同步处理。

       ä¸Šé¢è¿™ç§è¯´æ³•è‚¯å®šæ˜¯æ­£ç¡®çš„,对照一下StringBuilder和StringBuffer的部分源代码也能够看出来。

       StringBuilder的append方法源代码:

       @Override

       public StringBuilder append(String str) {

       super.append(str);

       return this;

       }

       StringBuffer的append方法源代码:

       @Override

       public synchronized StringBuffer append(String str) {

       toStringCache = null;

       super.append(str);

       return this;

       }

为什么?为什么StringBuilder是线程不安全的?

       在比较 String、StringBuilder 和 StringBuffer 时,提及了 StringBuilder 是非线程安全的,那么其原因何在?

       在查看 StringBuilder 或 StringBuffer 的源码后,可以发现 StringBuilder 在 append 操作中并未使用线程同步,而 StringBuffer 在大部分方法中使用了 synchronized 关键字进行方法级别的同步。这种说法是正确的,通过对比源码亦能验证。

       然而,这并未解释为何 StringBuilder 会是线程不安全的,为何需要使用 synchronized 来确保线程安全?以及如果未使用同步会发生什么异常?

       接下来,我们将分别解答以上问题。

       通过示例代码,构建一个 StringBuilder,并创建 个线程,每个线程拼接字符串 "a" 次。理论上,完成线程执行后,打印的结果应为 ,但多次执行后,打印结果通常少于 ,且存在一定概率出现异常信息。

       StringBuilder 线程不安全的原因在于其内部处理字符串的两个关键成员变量:char 数组 value 和 count。StringBuilder 通过不断扩容和增加 count 来实现字符串的 append 操作。在 append 方法中,count 的 "+= 操作是线程不安全的,可能导致两个线程同时读取到 count 值为 5,执行加 1 操作后,都变为 6,而非预期的 7,导致不期望的结果。

       在异常堆栈信息中,可以发现发生异常的代码在 AbstractStringBuilder 的 append 方法中。核心操作为将传入的 String 对象复制到 value 中。异常发生的原因是程序试图访问下标为 7 的位置,而此时 value 的实际下标只到 6。这与 count 被错误地少加有关。在执行 str.getChars 方法之前,需根据 count 校验 value 是否已用尽,若已用尽,则进行扩容。append 方法中的对应代码为:

       确保容量内部的具体实现:

       当 count 应为 7 而 value 长度为 6 时,本应触发扩容。但由于并发导致 count 为 6,假设 len 为 1,则传递的 minimumCapacity 为 7,并不会进行扩容操作。这导致后续执行 str.getChars 方法进行复制操作时访问不存在的位置,从而抛出异常。

       在此基础上,我们简单查看了扩容方法中的 newCapacity 方法,核心是将新数组长度扩充为原来的两倍再加 2,作为 Arrays.copyOf 的参数进行扩容。

       通过上述分析,我们真正理解了 StringBuilder 线程不安全的原因。在学习和实践中,不仅应掌握结论,还需理解其底层原理,并学会分析底层原理的方法。

面试篇==和equals()区别、String线程安全问题(StringBuilder)

       equals(值相等) ==(引用相等)

       equals源代码中可以看到:

       JDK自带的equals有两种,针对Object对象及String对象

       1、String中的equals

       ==判断是否相等,相等直接返回true->再判断是否为string类型,否直接返回false->是则继续判断对象length->循环判断char是否相等(jdk8使用的是char,高版本的jdk已使用效率更高的byte)

       2、Object中的equals

       直接return (this == obj),一般业务对象比较要改造equals方法

       p.s.自定义对象需要重写equals

       二、String线程安全问题

       String中的对象是不可变的,也就可以理解为常量,线程安全。AbstractStringBuilder 是 StringBuilder 与 StringBuffer 的公共父类,定义了一些字符串的基本操作,如 expandCapacity、append、insert、indexOf 等公共方法。StringBuffer 对方法加了同步锁或者对调用的方法加了同步锁,所以是线程安全的。StringBuilder 并没有对方法进行加同步锁,所以是非线程安全的。

搜索关键词:chardet源码