`
Cwind
  • 浏览: 262814 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
博客专栏
793bb7df-a2a9-312d-8cb8-b66c3af482d1
LeetCode题解
浏览量:52417
社区版块
存档分类
最新评论

StringBuffer与StringBuilder的线程安全性验证

    博客分类:
  • Java
阅读更多
对于国内面试中经常问“StringBuffer和StringBuilder有何区别”,知乎上曾有一番讨论。
我以为,好的面试官可以在这个问题上直接进一步,“你不知道这两个的区别没关系,我可以告诉你,我们聊聊短生命周期对象管理和线程安全性吧。”所以取而代之的这样的一个问题就更有意义了:请写一个程序来验证StringBuffer和StringBuilder的线程安全性。
 
线程安全性是指,当对一个复杂对象进行某种操作时,从操作开始到操作结束之前,该对象会经历若干中间状态,直到操作完全结束,该对象才会会到完全可用的状态。如果其他线程能够访问处于不可用中间状态的对象,使该对象产生无法预料的结果,则称该对象线程不安全,反之则称其为线程安全。
 
所以这个简单程序的考察点:
  • 线程安全性的理解
  • Java并发编程基础
  • 主动思考和分析能力,以及去求证的主动性,而不是被动接受各种结论

 

示例程序如下:
public class StringBufferAndStringBuilderTest {

    private static final int THREAD_NUM = 1000;

    public static void main(String[] args){
        long startTime = System.currentTimeMillis();
        String strToReverse = "AAAABBBB";

        StringBuffer stringBuffer = new StringBuffer(strToReverse);
        StringBuilder stringBuilder = new StringBuilder(strToReverse);
        CountDownLatch countDownLatch = new CountDownLatch(THREAD_NUM);
        CountDownLatch countDownLatch2 = new CountDownLatch(THREAD_NUM);

        for(int i=0; i<THREAD_NUM; i++) {
            new StringBufferTaskThread(stringBuilder, countDownLatch).start();
            new StringBufferTaskThread(stringBuffer, countDownLatch2).start();
        }

        try {
            countDownLatch.await();
            countDownLatch2.await();
            System.out.println("StringBuffer toString: " + stringBuffer.toString());
            System.out.println("StringBuilder toString: " + stringBuilder.toString());
            long endTime = System.currentTimeMillis();
            System.out.println("Running time: " + (endTime-startTime));
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
class StringBufferTaskThread extends Thread {
    private static final String STARTER = "-start";
    private static final String ENDER = "-end";

    private Object s = null;
    private CountDownLatch countDownLatch;  // 记载运行线程数

    public StringBufferTaskThread(StringBuilder stringBuilder, CountDownLatch countDownLatch) {
        super();
        this.s = stringBuilder;
        this.countDownLatch = countDownLatch;
    }

    public StringBufferTaskThread(StringBuffer stringBuffer, CountDownLatch countDownLatch) {
        super();
        this.s = stringBuffer;
        this.countDownLatch = countDownLatch;
    }

    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName() + STARTER);
        for(int i=0; i<10; i++) {
            try {
                Thread.sleep(200);
                if(s instanceof StringBuffer){
                    ((StringBuffer) s).reverse();
                    System.out.println("Buffer->"+s.toString());
                }else if(s instanceof StringBuilder){
                    ((StringBuilder) s).reverse();
                    System.out.println("Builder->"+s.toString());
                }
                Thread.sleep(200);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        System.out.println(Thread.currentThread().getName() + ENDER);
        countDownLatch.countDown();
    }
}
此示例程序做了如下事情:
  • 基于初始字符串“AAAABBBB”分别构建StringBuffer和StringBuilder对象
  • 分别启动1000个线程,调用StringBuffer和StringBuilder的reverse方法,进行字符串反转
  • 所有线程执行完后打印结果,由于反转偶数次,线程安全的对象输出应与初始值相同,线程不安全的对象则可能产生乱序
输出:
Thread-0-start
Thread-1-start
Thread-2-start
Thread-3-start
Thread-4-start
Thread-5-start
Thread-6-start
Thread-7-start
....
Thread-368-end
Thread-1809-end
Thread-1609-end
Thread-1810-end
Thread-1608-end
Thread-1702-end
Thread-1527-end
StringBuffer toString: AAAABBBB
StringBuilder toString: ABBBBBAB
Running time: 7523
发现StringBuffer输出与初始值相同,StringBuilder输出产生乱序。多次执行或调大线程数StringBuffer输出结果不变,由此二者线程安全性得证。
2
1
分享到:
评论
4 楼 Cwind 2017-01-12  
faradayroger 写道
class StringBufferTaskThread这个类要改成静态的

为什么呢?
3 楼 faradayroger 2017-01-11  
class StringBufferTaskThread这个类要改成静态的
2 楼 Cwind 2017-01-11  
java-lxm 写道
没看懂

补充了一点示例程序和输出结果说明
1 楼 java-lxm 2017-01-11  
没看懂

相关推荐

Global site tag (gtag.js) - Google Analytics