StringBuffer是一个线程安全的可变序列的字符数组对象,它与StringBuilder一样,继承父类AbstractStringBuilder。在多线程环境中,当方法操作是必须被同步,StringBuffer内的方法被同步化时,以实现跟在单线程中操作一样的一致性。

public final class StringBuffer extends AbstractStringBuilder implements java.io.Serializable, CharSequence {//一个缓存用来存储最后一次调用toString返回的值,每当StringBuffer被修改就把该缓存清空private transient char[] toStringCache;public StringBuffer() {super(16);}public StringBuffer(int capacity) {super(capacity);}//...more constructs,提供与父类一致的构造器,StringBuffer的构造器总是调用父类的构造器
@Overridepublic synchronized int length() {//返回容器中字符的数量return count;}@Overridepublic synchronized int capacity() {//返回容器的大小return value.length;}@Overridepublic synchronized void ensureCapacity(int minimumCapacity) {//保证容器足够大if (minimumCapacity > value.length) {expandCapacity(minimumCapacity);}}@Overridepublic synchronized void trimToSize() {//将容器的大小与容器的字符数量变成一致的super.trimToSize();}//setLength是修改了StringBuffer,所以要把toStringCache设置为nullpublic synchronized void setLength(int newLength) {toStringCache = null;super.setLength(newLength);}//...append,insert方法还有其他需要同步化的方法都是覆盖父类,用synchronized使方法同步化,同时那些修改了StringBuffer的方法,需要先把toStringCache设置为null//下面几个insert方法没有用synchronized来实现同步化,上面的解释说这些方法的同步化是通过调用其他StringBuffer方法来实现的public StringBuffer insert(int dstOffset, CharSequence s) {// Note, synchronization achieved via invocations of other StringBuffer methods// after narrowing of s to specific type// Ditto for toStringCache clearingsuper.insert(dstOffset, s);return this;}public  StringBuffer insert(int offset, boolean b) {// Note, synchronization achieved via invocation of StringBuffer insert(int, String)// after conversion of b to String by super class method// Ditto for toStringCache clearingsuper.insert(offset, b);return this;}public StringBuffer insert(int offset, int i) {// Note, synchronization achieved via invocation of StringBuffer insert(int, String)// after conversion of i to String by super class method// Ditto for toStringCache clearingsuper.insert(offset, i);return this;}public StringBuffer insert(int offset, long l) {// Note, synchronization achieved via invocation of StringBuffer insert(int, String)// after conversion of l to String by super class method// Ditto for toStringCache clearingsuper.insert(offset, l);return this;}public StringBuffer insert(int offset, float f) {// Note, synchronization achieved via invocation of StringBuffer insert(int, String)// after conversion of f to String by super class method// Ditto for toStringCache clearingsuper.insert(offset, f);return this;}public StringBuffer insert(int offset, double d) {// Note, synchronization achieved via invocation of StringBuffer insert(int, String)// after conversion of d to String by super class method// Ditto for toStringCache clearingsuper.insert(offset, d);return this;}public int indexOf(String str) {// Note, synchronization achieved via invocations of other StringBuffer methodsreturn super.indexOf(str);}public int lastIndexOf(String str) {// Note, synchronization achieved via invocations of other StringBuffer methodsreturn lastIndexOf(str, count);}//这个toString方法很重要,如果toStringCache为null时,会把当前的value复制一份新的给它,否则返回String(toStringCache)public synchronized String toString() {if (toStringCache == null) {toStringCache = Arrays.copyOfRange(value, 0, count);}return new String(toStringCache, true);}//下面的三个方法是为了实现StringBuffer的序列化和反序列化private static final java.io.ObjectStreamField[] serialPersistentFields ={new java.io.ObjectStreamField("value", char[].class),new java.io.ObjectStreamField("count", Integer.TYPE),new java.io.ObjectStreamField("shared", Boolean.TYPE),};private synchronized void writeObject(java.io.ObjectOutputStream s)throws java.io.IOException {java.io.ObjectOutputStream.PutField fields = s.putFields();fields.put("value", value);fields.put("count", count);fields.put("shared", false);s.writeFields();}private void readObject(java.io.ObjectInputStream s)throws java.io.IOException, ClassNotFoundException {java.io.ObjectInputStream.GetField fields = s.readFields();value = (char[])fields.get("value", null);count = fields.get("count", 0);}

从上面源码可知,StringBuffer将父类非线程安全的方法都覆盖实现同步化,它自己拥有一个toStringCache的缓存,当这个缓存为空的时候,就知道StringBuffer被修改过了,这时候调用toString方法,就能得到被修改后最新的值。

转载于:https://www.cnblogs.com/13jhzeng/p/5624424.html

java.lang.StringBuffer源码分析相关推荐

  1. Java集合类框架源码分析 之 LinkedList源码解析 【4】

    上一篇介绍了ArrayList的源码分析[点击看文章],既然ArrayList都已经做了介绍,那么作为他同胞兄弟的LinkedList,当然必须也配拥有姓名! Talk is cheap,show m ...

  2. java.util.ServiceLoader源码分析

    java.util.ServiceLoader源码分析 回顾: ServiceLoader类的使用(具体参考博客http://blog.csdn.net/liangyihuai/article/det ...

  3. 并发编程5:Java 阻塞队列源码分析(下)

    上一篇 并发编程4:Java 阻塞队列源码分析(上) 我们了解了 ArrayBlockingQueue, LinkedBlockingQueue 和 PriorityBlockingQueue,这篇文 ...

  4. Java并发-ReentrantReadWriteLock源码分析

    ReentrantLock实现了标准的互斥重入锁,任一时刻只有一个线程能获得锁.考虑这样一个场景:大部分时间都是读操作,写操作很少发生:我们知道,读操作是不会修改共享数据的,如果实现互斥锁,那么即使都 ...

  5. java activerecord.db_JFinal 源码分析 [DB+ActiveRecord]

    我记得以前有人跟我说,"面试的时候要看spring的源码,要看ioc.aop的源码"那为什么要看这些开源框架的源码呢,其实很多人都是"应急式"的去读,就像读一篇 ...

  6. Java中ArrayList源码分析

    一.简介 ArrayList是一个数组队列,相当于动态数组.每个ArrayList实例都有自己的容量,该容量至少和所存储数据的个数一样大小,在每次添加数据时,它会使用ensureCapacity()保 ...

  7. Java容器 | 基于源码分析List集合体系

    一.容器之List集合 List集合体系应该是日常开发中最常用的API,而且通常是作为面试压轴问题(JVM.集合.并发),集合这块代码的整体设计也是融合很多编程思想,对于程序员来说具有很高的参考和借鉴 ...

  8. java并发:join源码分析

    join join join是Thread方法,它的作用是A线程中子线程B在运行之后调用了B.join(),A线程会阻塞直至B线程执行结束 join源码(只有继承Thread类才能使用) 基于open ...

  9. 【Java】equals源码分析

    源码分析 This class consists of static utility methods for operating on objects. These utilities include ...

最新文章

  1. python 语料标注_在python中怎么标记文本?
  2. [詹兴致矩阵论习题参考解答]习题6.6
  3. 只用一张图+相机走位,AI就能脑补周围环境,来自华人团队 | CVPR2022
  4. 小白科普:虚拟化简史
  5. 史上最全SQL优化方案
  6. Android探索之旅 | 面向对象和Java基础
  7. matlab重叠相加法求卷积,通过重叠相加法实现卷积的报告.doc
  8. linux命令怎么调wsdl,如何从命令行执行SOAP wsdl Web服务调用
  9. Mysql 中的SSL 连接
  10. shell脚本中的日期处理
  11. cmd bat 相对命令
  12. NOIP模拟题 栅栏
  13. 人工智能白皮书(2022年) 附下载
  14. 取消字体许可限制_字体许可和使用:您需要知道的
  15. 腾讯云实验室linux基本操作
  16. php外包如何逃离垃圾客户案例(转)
  17. web安全:QQ号快速登录漏洞及被盗原理
  18. sencha list
  19. 十七、电话号码的字母组合
  20. EDM邮件营销的七个基本原则

热门文章

  1. Server.MapPath() 探究
  2. windows7下修改hosts文件无效解决办法(转)
  3. 指定linux软件安装路径
  4. Akka Actor Inbox_信箱
  5. Dynamips 7200
  6. ubuntu系统颜色更改
  7. Windows2003环境下的一键系统安全
  8. 使用 ADO 向数据库中存储一张图片
  9. Linux fread函数例程,21.2.9 文件读写实例--实现cp命令
  10. 大数据项目实战数仓4——总纲