我正在阅读关于使用StringBuilder与StringBuffer的Stackoverflow thread。
底线似乎是两个集合是相同的,除了StringBuffer是同步的,是一个线程安全的,并且与StringBuilder相比性能稍差,而不是那些东西。
有人提到了ArrayList和Vector之间存在类似的关系。
除非我有意识地创建多个线程,否则不使用同步集合(或其他任何东西)是否是一个好的(安全的)经验法则?
换句话说,我收到消息“尽可能使用新的StringBuilder。”,我想知道的是,我怎么能确定它是否可能?
只要我不故意创建新线程,我是否可以安全地使用非同步集合?
答案 0 :(得分:5)
使用不同步的内容,直到您确定需要同步为止。
部分问题,例如StringBuffer
和Vector
是他们并不总是以正确的方式同步。对于Vector
,并不总是您需要使每个操作单独同步;通常你真正想要的是同步操作块...... Vector
不一定比ArrayList
或Collections.synchronizedList
好。
当您知道自己正在使用并发和多线程时,请计算出所需的同步详细信息,但只需将StringBuffer
换成StringBuilder
只会给您一种错误的安全感 - 即使您决定稍后使用并发,也不一定是并发的种。
(如果您当前没有使用线程,那么绝对没问题 - 甚至建议 - 查找并替换StringBuffer
到StringBuilder
。上述参数用于反向。 )
答案 1 :(得分:1)
我会说在你知道如何自己回答这个问题之前,总是使用非阻塞的东西。它很容易同步一切,它也非常容易创建和启动线程。需要一段时间才能了解何时使用synchronized以及何时创建线程。
您应该首先阅读Java Concurrency in Practice。
答案 2 :(得分:1)
好像你在这里问了多个问题。所以,首先,除非绝对必要,否则避免同步确实是一个好主意。
关于第二个问题,将StringBuilder替换为StringBuffer也是安全的,反之亦然,除非可以从多个线程更改它们的值。
答案 3 :(得分:0)
我们正在使用StringBuilder
而不是StringBuffer
,因为我们认为多线程不会导致我们出现问题。
答案 4 :(得分:0)
在没有进一步分析的情况下,在整个代码库上执行此操作会自动听起来有点危险,除非您100%肯定这些对象(Vectors,StringBuffers)不是在线程之间共享,或者是否未选择同步对象首先通过线程安全分析。
一个可以无风险地进行交换的简单情况是局部变量,显然不能在线程上共享(除非你返回它们)。
答案 5 :(得分:0)
此链接说得最好:
* http://javahowto.blogspot.com/2006/08/stringbuilder-vs-stringbuffer.html
StringBuilder是在JDK 1.5中引入的。有什么区别 StringBuilder和StringBuffer?根据javadoc,StringBuilder是 在单线程用法中设计为StringBuffer的替代品。 他们在简单术语上的主要区别是:
StringBuffer设计为线程安全的,并且StringBuffer中的所有公共方法都是同步的。 StringBuilder没有 处理线程安全问题,并且没有任何方法同步。
在大多数情况下,StringBuilder的性能优于StringBuffer。
尽可能使用新的StringBuilder。
根据我自己的经验:
对于任何严重的字符串操作,始终使用StringBuilder(从不“字符串”)
我从来没有机会使用StringBuffer(我总是只使用“StringBuilder”)。
只有当从多个线程同时访问相同的正在进行的字符串时,您才应该考虑“StringBuffer”。即便如此,您可能会发现使用自己的锁定更容易/更有效。
... IMHO
答案 6 :(得分:0)
除非我有意识地创建多个线程,否则不使用同步集合(或其他任何东西)是否是一个好的(安全的)经验法则?
不,不是。
有些情况下涉及多个线程,即使您没有有意识地创建它们。例如,任何使用Swing或Servlet的应用程序都有可能在不同线程上的应用程序代码之间进行交互。 (如果你使用标准的线程池实现,你甚至可以说你没有显式地创建线程。)
此外,使用同步集合并不一定会为您带来线程安全性。
但是,在没有多线程使用数据结构的情况下使用同步数据结构时,你是正确的(有点)浪费。但是,在过去互联网价格昂贵的时代,没有任何地方像浪费一样浪费。
换句话说,我收到消息“尽可能使用新的StringBuilder。”,我想知道的是,我怎么能确定它是否可能?
了解您的代码。其他线程可以看到StringBuilder
吗?如果没有,那么使用它是安全的。否则,共享StringBuilder
的线程需要同步。一种方法可能使用StringBuffer
,但必然不会为您提供正确的同步粒度。
这是一个简单的例子:
public String nTimes(String str, int n) {
StringBuilder sb = new StringBuilder();
for (int i = 1; i <= n; i++) sb.append(str);
return sb.toString();
}
在上文中,StringBuilder
中的sb
永远不会被另一个线程看到,因此无需同步它。