博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
再谈StringBuilder和StringBuffer的区别
阅读量:4219 次
发布时间:2019-05-26

本文共 3188 字,大约阅读时间需要 10 分钟。

通常字符串的拼接我们可能会用加号"+"拼接,或者用StringBuilder、StringBuffer进行拼接。已经知道加号"+"拼接的字符串可能会创建多个对象(注意:我用的是可能,因为在一两个的拼接时候,jdk编译器会帮我们优化,而没有创建多个对象,不过,对于for循环里面的字符串拼接,推荐用StringBuilder或者StringBuffer)。
区别:StringBuilder是
线程不安全的,而StringBuffer是
线程安全的。
测试栗子如下:

1、利用StringBuilder来拼接5000个单个字符,预计拼接后的长度为5000,如果不是5000,则不是线程安全的。

@Slf4jpublic class StringExample1 {    //  请求总数    public static int clientTotal = 5000;    // 同时并发执行的线程数    public static int threadTotal = 200;    public static StringBuilder stringBuilder = new StringBuilder();    public static void main(String[] args) throws InterruptedException {        ExecutorService executorService = Executors.newCachedThreadPool();        final Semaphore semaphore = new Semaphore(threadTotal);        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);        for (int i = 0; i< clientTotal; i ++) {            executorService.execute(()->{                try {                    semaphore.acquire();                    update();                    semaphore.release();                } catch (InterruptedException e) {                    e.printStackTrace();                }                countDownLatch.countDown();            });        }        countDownLatch.await();        executorService.shutdown();        log.info("size:{}", stringBuilder.length());    }        public static void update() {        stringBuilder.append("i");    }}
输出:
[main] INFO com.example.concurrent.commonUnsafe.StringExample1 - size:4963
1、利用
StringBuffer来拼接5000个单个字符,预计拼接后的长度为5000,如果不是5000,则不是线程安全的。
@Slf4jpublic class StringExample2 {    //  请求总数    public static int clientTotal = 5000;    // 同时并发执行的线程数    public static int threadTotal = 200;    public static StringBuffer stringBuffer = new StringBuffer();    public static void main(String[] args) throws InterruptedException {        ExecutorService executorService = Executors.newCachedThreadPool();        final Semaphore semaphore = new Semaphore(threadTotal);        final CountDownLatch countDownLatch = new CountDownLatch(clientTotal);        for (int i = 0; i< clientTotal; i ++) {            executorService.execute(()->{                try {                    semaphore.acquire();                    update();                    semaphore.release();                } catch (InterruptedException e) {                    e.printStackTrace();                }                countDownLatch.countDown();            });        }        countDownLatch.await();        executorService.shutdown();        log.info("size:{}", stringBuffer.length());    }    public static void update() {        stringBuffer.append("i");    }}
输出:
[main] INFO com.example.concurrent.commonUnsafe.StringExample2 - size:5000
分析:StringBuilder和StringBuffer内部实现机制的不同:
StringBuffer的所有方法都加了Synchronized关键字,比如:
stringBuffer
.append(
"i"
);
这里面的append方法的源码为:
@Overridepublic synchronized StringBuffer append(String str) {    toStringCache = null;    super.append(str);    return this;}
总结:
既然StringBuilder是线程不安全的,为什么还要使用StringBuilder,很明显线程安全的StringBuffer是同synchronized关键字来保证同一时间只能有一个线程调用该方法,因此在性能上是有损耗的。如果不是在并发情况下,我们通常字符串的拼接是在一个方法内部的局部变量(局部变量是堆栈封闭的,是线程安全的),因此,此时选择StringBuilder的性能更高。
局部变量用StringzBuilder,
全局变量用StringBuilder。

转载地址:http://lgomi.baihongyu.com/

你可能感兴趣的文章
图解后缀表达式的计算过程
查看>>
栈与队列的应用——计算表达式的值
查看>>
静态链表——sharing
查看>>
静态链表——sorting
查看>>
DFS——背包问题
查看>>
DFS——选数问题
查看>>
BFS——求矩阵中“块”的个数
查看>>
BFS——走迷宫的最小步数
查看>>
并查集——好朋友
查看>>
关键路径
查看>>
Web前端学习笔记——JavaScript之事件详解
查看>>
Web前端学习笔记——JavaScript之事件、创建元素、节点操作
查看>>
Web前端学习笔记——JavaScript之正则表达式、伪数组、垃圾回收
查看>>
Web前端学习笔记——JavaScript 之继承、函数进阶
查看>>
Web前端学习笔记——JavaScript之面向对象游戏案例:贪吃蛇
查看>>
不做单元测试?小心得不偿失!嵌入式系统单元测试工具,自动生成测试用例
查看>>
一种实用的联网汽车无线攻击方法及车载安全协议
查看>>
光靠欺骗检测是不够的:对抗多目标跟踪的攻击
查看>>
基于微区块链的V2X地理动态入侵检测
查看>>
面向V2C场景的ADAS数字孪生模型构建方法
查看>>