为什么不要用 StringBuffer 和 Vector

来源:互联网 发布:凯立德端口查看 编辑:程序博客网 时间:2024/04/29 01:46

把贴吧一大神(那十无忧)的文章总结到此:

http://tieba.baidu.com/p/1443344962#0-qzone-1-78428-d020d2d2a4e8d1a374a433f596ad1440

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

很多人在回答新手提问的时候会说,StringBuilder 是非同步的,所以快一些,StringBuffer是同步(线程An全)的,所以慢一些。从技术上说这句话是没有错的,但是为什么又不要用 StringBuffer 呢?

简单的说,StringBuffer的“线程An全”在大多数时候增加了大量不必要的成本,并且未必达到目的。
看下面的代码:

StringBuffer buffer = getStringBuffer();
for(int i=0; i<10000; i++)
buffer.append(i);

StringBuffer 的每一步操作都先获取同步锁,然后释放同步锁。
所以这段代码中,它获取了10000次锁,释放了10000次锁。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

除了获取、释放10000次锁的高昂成本之外,它真的实现了“线程AN全”的目的吗?

假如在这个for循环运行的过程中,有另一个线程对 buffer 做了操作:

buffer.append("some string");

那么这个 "some string" 就会**入某两个数字之间!因为在任意两次 append 数字之间,有一个“释放锁”再“获取锁”的极短暂的间隔,这时候是可以被其他线程获取锁的。
换句话说,StringBuffer 所提供的所谓“线程AN全”,并不包括多个操作之间的“原子性”支持。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

要想前述的for循环不受干扰地完成,用户还是需要手动上锁:

final StringBuffer buffer = getStringBuffer();
synchronized(buffer) {
for(int i=0; i<10000; i++)
buffer.append(i);
}

这样是保证了在for循环运行期间不受其他线程干扰,可是如前所述,10000次锁值 +1 和 -1 的成本还是有的,并且这个成本变成了“完全没有必要”的无意义成本。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

这就是为什么 StringBuffer 这个类天生缺陷。
在API设计中有一条规则是这样说的:

一个类不应该自己实现同步,而应该把同步的工作留给用户。

这句话也是本帖的目的所在: 在绝大多数情况下,把同步的工作留给应用代码,而不是工具类的代码。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------

各位看官可以拜访原帖,浏览评论交流内容~


这位大神如果不高兴.......................................不高兴你来喷我啊!


0 0
原创粉丝点击