有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!


共 (1) 个答案

  1. # 1 楼答案

    嗯,我认为强调StringBuffer的一些实际用途是很重要的。为此,我设计了一个简单的程序来说明StringBuffer在实现线程安全方面如何优于StringBuilder

    /**
     * Run this program a couple of times. We see that the StringBuilder does not
     * give us reliable results because its methods are not thread-safe as compared
     * to StringBuffer.
     * 
     * For example, the single append in StringBuffer is thread-safe, i.e.
     * only one thread can call append() at any time and would finish writing
     * back to memory one at a time. In contrast, the append() in the StringBuilder 
     * class can be called concurrently by many threads, so the final size of the 
     * StringBuilder is sometimes less than expected.
     * 
     */
    public class StringBufferVSStringBuilder {
    
        public static void main(String[] args) throws InterruptedException {
    
            int n = 10; 
    
            //*************************String Builder Test*******************************//
            StringBuilder sb = new StringBuilder();
            StringBuilderTest[] builderThreads = new StringBuilderTest[n];
            for (int i = 0; i < n; i++) {
                builderThreads[i] = new StringBuilderTest(sb);
            }
            for (int i = 0; i < n; i++) {
                builderThreads[i].start();
            }
            for (int i = 0; i < n; i++) {
                builderThreads[i].join();
            }
            System.out.println("StringBuilderTest: Expected result is 1000; got " + sb.length());
    
            //*************************String Buffer Test*******************************//
    
            StringBuffer sb2 = new StringBuffer();
            StringBufferTest[] bufferThreads = new StringBufferTest[n];
            for (int i = 0; i < n; i++) {
                bufferThreads[i] = new StringBufferTest(sb2);
            }
            for (int i = 0; i < n; i++) {
                bufferThreads[i].start();
            }
            for (int i = 0; i < n; i++) {
                bufferThreads[i].join();
            }
            System.out.println("StringBufferTest: Expected result is 1000; got " + sb2.length());
    
        }
    
    }
    
    // Every run would attempt to append 100 "A"s to the StringBuilder.
    class StringBuilderTest extends Thread {
    
        StringBuilder sb;
    
        public StringBuilderTest (StringBuilder sb) {
            this.sb = sb;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                sb.append("A");
            }
    
        }
    }
    
    
    //Every run would attempt to append 100 "A"s to the StringBuffer.
    class StringBufferTest extends Thread {
    
        StringBuffer sb2;
    
        public StringBufferTest (StringBuffer sb2) {
            this.sb2 = sb2;
        }
    
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                sb2.append("A");
            }
    
        }
    }
    

    然而,正如许多其他人也指出的那样,StringBuffer并不是设计线程安全应用程序的灵丹妙药更进一步,我要说的是,用于并发的工具和库(例如Vector)应该得到很好的理解和适当的实现,我们不应该简单地假设使用“线程安全”库

    http://jeremymanson.blogspot.sg/2008/08/dont-use-stringbuffer.html

    杰里米的例子说明了这一点,我引用:

    Thread 1:
    sb.append("a");
    
    Thread 2:
    sb.append("b");
    
    Thread 3:
    join 1,2
    print(sb.toString());
    

    当然,它是“线程安全的”,即不存在数据竞争(基本上是没有足够同步的并发访问)。但是您不知道线程3将打印什么:“ab”或“ba”“。我必须引入更多的同步,使其产生合理的结果。StringBuffer附带的锁没有任何帮助。”

    我希望这对你是有见地的