为什么要使用StringBuilder? StringBuffer可以使用多个线程以及一个线程吗?

时间:2011-05-30 09:02:59

标签: java multithreading synchronization stringbuilder stringbuffer

假设我们的应用程序只有一个线程。我们正在使用StringBuffer那么问题是什么?

我的意思是如果StringBuffer可以通过同步处理多个线程,那么单线程有什么问题?

为什么要使用StringBuilder

8 个答案:

答案 0 :(得分:27)

StringBuffers是线程安全的,这意味着它们具有控制访问的同步方法,因此一次只有一个线程可以访问StringBuffer对象的同步代码。因此,StringBuffer对象通常可以安全地在多线程环境中使用,其中多个线程可能试图同时访问同一个StringBuffer对象。

StringBuilder's访问未同步,因此它不是线程安全的。通过不同步,StringBuilder的性能可以比StringBuffer更好。因此,如果您在单线程环境中工作,则使用StringBuilder而不是StringBuffer可能会提高性能。对于其他情况也是如此,例如StringBuilder局部变量(即方法中的变量),其中只有一个线程将访问StringBuilder对象。

所以,更喜欢StringBuilder因为,

  • 小的性能提升。
  • StringBuilder是StringBuffer类的1:1替代品。
  • StringBuilder不是线程同步的,因此在大多数Java实现上都表现得更好

检查出来:

答案 1 :(得分:7)

StringBuilder应该更快(微小),因为它不同步(线程安全)。

您可以注意到真正繁重的应用程序存在差异。

  

StringBuilder类通常应优先于此使用,因为它支持所有相同的操作,但速度更快,因为它不执行同步。

http://download.oracle.com/javase/6/docs/api/java/lang/StringBuffer.html

答案 2 :(得分:5)

在多个线程中使用StringBuffer是无用的,实际上几乎从未发生过。

考虑以下

Thread1: sb.append(key1).append("=").append(value1);
Thread2: sb.append(key2).append("=").append(value2);

每个追加都是同步的,但是线程可以随时弯腰,这样你就可以拥有以下任何组合和更多

key1=value1key2=value2
key1key2==value2value1
key2key1=value1=value2
key2=key1=value2value1

这可以通过一次同步整行来避免,但是这使得使用StringBuffer而不是StringBuilder失败了。

即使你有一个正确同步的视图,它也比创建整行的线程本地副本更复杂,例如StringBuilder和日志行一次到类似Writer的类。

答案 3 :(得分:3)

StringBuffer在单线程应用程序中不是错误。它的工作方式与StringBuilder一样。

唯一的区别是拥有所有同步方法所带来的微小开销,这在单线程应用程序中没有任何优势。

我的观点是引入了 main 原因StringBuilder是编译器在编译包含{的代码时使用StringBuffer(现在是StringBuilder) {1}}连接:在这些情况下,同步永远不会,并且使用未同步的String替换所有这些地方可以提供较小的性能提升。

答案 4 :(得分:2)

StringBuilder具有更好的性能,因为它的方法不同步。

因此,如果你不需要同时构建一个String(这是一个相当不典型的场景),那么就没有必要为不必要的同步开销“付费”。

答案 5 :(得分:0)

这会帮助你们, Be Straight Builder比Buffer慢,

public class ConcatPerf {
        private static final int ITERATIONS = 100000;
        private static final int BUFFSIZE = 16;

        private void concatStrAdd() {
            System.out.print("concatStrAdd   -> ");
            long startTime = System.currentTimeMillis();
            String concat = new String("");
            for (int i = 0; i < ITERATIONS; i++) {
                concat += i % 10;
            }
            //System.out.println("Content: " + concat);
            long endTime = System.currentTimeMillis();
            System.out.print("length: " + concat.length());
            System.out.println(" time: " + (endTime - startTime));
        }

        private void concatStrBuff() {
            System.out.print("concatStrBuff  -> ");
            long startTime = System.currentTimeMillis();
            StringBuffer concat = new StringBuffer(BUFFSIZE);
            for (int i = 0; i < ITERATIONS; i++) {
                concat.append(i % 10);
            }
            long endTime = System.currentTimeMillis();
            //System.out.println("Content: " + concat);
            System.out.print("length: " + concat.length());
            System.out.println(" time: " + (endTime - startTime));
        }

        private void concatStrBuild() {
            System.out.print("concatStrBuild -> ");
            long startTime = System.currentTimeMillis();
            StringBuilder concat = new StringBuilder(BUFFSIZE);
            for (int i = 0; i < ITERATIONS; i++) {
                concat.append(i % 10);
            }
            long endTime = System.currentTimeMillis();
           // System.out.println("Content: " + concat);
            System.out.print("length: " + concat.length());
            System.out.println(" time: " + (endTime - startTime));
        }

        public static void main(String[] args) {
            ConcatPerf st = new ConcatPerf();
            System.out.println("Iterations: " + ITERATIONS);
            System.out.println("Buffer    : " + BUFFSIZE);

            st.concatStrBuff();
            st.concatStrBuild();
            st.concatStrAdd();
        }
    }

Output  

    run:
    Iterations: 100000
    Buffer    : 16
    concatStrBuff  -> length: 100000 time: 11
    concatStrBuild -> length: 100000 time: 4
    concatStrAdd   -> 

答案 6 :(得分:0)

Manish,虽然只有一个线程在你的StringBuffer实例上运行,但是只要调用任何方法,就会在StringBuffer实例上获取和释放监视器锁定时产生一些开销。因此,StringBuilder是单线程环境中的首选。

答案 7 :(得分:0)

同步对象的成本很高。不要将程序视为独立实体;当您阅读概念并将其应用于您在问题详细信息中提到的小程序时,这不是问题,当我们想要扩展系统时会出现问题。在这种情况下,您的单线程程序可能依赖于其他几个方法/程序/实体,因此同步对象可能会在性能方面造成严重的编程复杂性。因此,如果您确定不需要同步对象,那么您应该使用StringBuilder,因为它是一个很好的编程习惯。最后,我们想学习编程以制作可扩展的高性能系统,这就是我们应该做的!