黑马程序员技术交流社区

标题: StringBuffer是怎么实现安全性的[已解决] [打印本页]

作者: 王金科    时间: 2012-8-29 19:41
标题: StringBuffer是怎么实现安全性的[已解决]
本帖最后由 王金科 于 2012-8-30 11:32 编辑

话说StringBuffer与StringBuilder相比,更具安全性,那么StringBuffe是怎么样实现安全性的,谁能给我说说原理?
作者: 曹操    时间: 2012-8-29 19:55
如果我们的程序是在单线程下运行,或者是不必考虑到线程同步问题,我们应该优先使用StringBuilder类;当然,如果要保证线程安全,自然非 StringBuffer莫属了。
除了对多线程的支持不一样外,这两个类的使用几乎没有任何差别

作者: 曹操    时间: 2012-8-29 20:01
StringBuffer只是相对StringBuilder而言要安全  因为StringBuilder是在StringBuffer的基础上做了改进

StringBuilder是线程不同步的,StringBuffer是线程同步的。二者用法相同,但是StringBuilder效率较StringBuffer高。在开发单线程时用StringBuilder。
楼主一定会问为什么StringBuilder效率高 原因是:        提高效率的原理是单线程,没有锁的机制。操作容器的方法很多,增删改查,如果一个线程在添加,一个线程在删除,这样就降低了效率,在一个添加时不能删除,此时使用的是同一个锁,只要以判断锁就在消耗资源。
实现代码:
StringBuilder s1=new StringBuilder("hello");
StringBuilder S2=new StringBuilder("java");
Method(s1,s2);
Method(String s1,String s2)
{
        S1.append(s2);
        S1=s2;
}
输出结果:hello java java
作者: 曹操    时间: 2012-8-29 20:03
知道后者为什么效率高 同样就能反推出前者为什么更安全
作者: 吴通    时间: 2012-8-29 20:27

因为StringBuffer是线程同步的,而StringBuilder是线程不同步的,
由于StringBuffer线程同步,所以保证了数据存储和取出是不一致的,
也就是说当存储数据的时候就不能取,这样就使数据不会发生混乱,
保证了数据的安全。
而StringBuilder是线程非同步的,存储和获取可以同时发生,所以数
据会发生混乱,是不安全的。
虽然StringBuffer是比较安全的,但是由于每次执行都要判断锁,故
处理数据效率比较低,所以一般开发都建议用StringBuilder



作者: 陈莹    时间: 2012-8-29 20:27
StringBuffer可将字符串缓冲区安全地用于多个线程,可以在必要时对这些方法进行同步,而StringBuilder用在字符串缓冲区被单个线程使用的时候,不能实现同步。
StringBuffer之所以能实现同步是因为它的方法都是同步函数,被synchronized修饰。而StringBuilder中的方法都是普通方法。
下面拿append方法来说:
public synchronized StringBuffer append(Object obj) {
        super.append(String.valueOf(obj));
        return this;
}
上面这是StringBuffer中的append方法,被synchronized修饰,实现同步。
public StringBuilder append(Object obj) {
       return append(String.valueOf(obj));
}
这是StringBuilder中的append方法,就是一般的函数,不能实现同步。
其他函数也是如此,所以StringBuffer比StringBuilder安全,在多进程中能实现同步。
不过在单进程中,这两个效果是一样的,并且StringBuilder会比StringBuffer效率高一些。
作者: 贾成龙    时间: 2012-8-29 20:59
public final class StringBufferextends Objectimplements Serializable, CharSequence线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。

可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。

StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。

例如,如果 z 引用一个当前内容为 "start" 的字符串缓冲区对象,则此方法调用 z.append("le") 会使字符串缓冲区包含 "startle",而 z.insert(4, "le") 将更改字符串缓冲区,使之包含 "starlet"。

通常,如果 sb 引用 StringBuilder 的一个实例,则 sb.append(x) 和 sb.insert(sb.length(), x) 具有相同的效果。

当发生与源序列有关的操作(如源序列中的追加或插入操作)时,该类只在执行此操作的字符串缓冲区上而不是在源上实现同步。

每个字符串缓冲区都有一定的容量。只要字符串缓冲区所包含的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区数组。如果内部缓冲区溢出,则此容量自动增大。从 JDK 5 开始,为该类补充了一个单个线程使用的等价类,即 StringBuilder。与该类相比,通常应该优先使用 StringBuilder 类,因为它支持所有相同的操作,但由于它不执行同步,所以速度更快。


作者: 王金科    时间: 2012-8-29 21:57
陈莹 发表于 2012-8-29 20:27
StringBuffer可将字符串缓冲区安全地用于多个线程,可以在必要时对这些方法进行同步,而StringBuilder用在字 ...

你的意思是StringBuffer里的方法都被synchronized所修饰的吗?
作者: 陈莹    时间: 2012-8-29 22:08
王金科 发表于 2012-8-29 21:57
你的意思是StringBuffer里的方法都被synchronized所修饰的吗?

是的,那样方法就成同步的了,明白吗
作者: 王金科    时间: 2012-8-29 22:26
陈莹 发表于 2012-8-29 22:08
是的,那样方法就成同步的了,明白吗

我还要在思考思考
作者: 陈莹    时间: 2012-8-29 22:29
王金科 发表于 2012-8-29 22:26
我还要在思考思考

你可以看看StringBuilder和StringBuffer的源代码,比较一下它们的区别
作者: zhaosenyang    时间: 2012-8-30 10:25
可以看下源代码,StringBuffer里面的方法都有synchronized同步修饰的,除了点 他跟StringBuilder没什么区别
作者: 王金科    时间: 2012-8-30 11:32
现在明白了,问题已解决,原来在源码上就已加上了同步
作者: 贾成龙    时间: 2012-8-30 17:16
陈莹 发表于 2012-8-29 22:08
是的,那样方法就成同步的了,明白吗

现在明白了吧!




欢迎光临 黑马程序员技术交流社区 (http://bbs.itheima.com/) 黑马程序员IT技术论坛 X3.2