StringBuilder

package com.keytech.task;import java.util.concurrent.CountDownLatch;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;//线程不平安public class StringExample1 {    public static Integer clientTotal=5000;    public static Integer threadTotal=200;    public static StringBuilder stringBuilder=new StringBuilder();    public static void main(String[] args) throws  Exception{        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 (Exception e){                    e.printStackTrace();                }                countDownLatch.countDown();            });        }        countDownLatch.await();        executorService.shutdown();        System.out.println("size"+stringBuilder.length());    }    private static void update() {        stringBuilder.append("1");    }}//size:4999
main函数中输入的后果不为预期的5000,并且每次后果可能会不统一,因而StringBuilder是线程不安全类

StringBuffer

package com.keytech.task;import java.util.concurrent.CountDownLatch;import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.Semaphore;//线程平安public class StringExample2 {    public static Integer clientTotal=5000;    public static Integer threadTotal=200;        public static StringBuffer stringBuffer=new StringBuffer();    public static void main(String[] args)  throws Exception{        ExecutorService executorService = Executors.newCachedThreadPool();        final Semaphore semaphore=new Semaphore(threadTotal);        final CountDownLatch countDownLatch=new CountDownLatch(threadTotal);        for (int i = 0; i < clientTotal; i++) {             executorService.execute(()->{                 try{                     semaphore.acquire();                     update();                     semaphore.release();                 }catch (Exception e){                     e.printStackTrace();                 }                 countDownLatch.countDown();             });        }        countDownLatch.await();        executorService.shutdown();        System.out.println("size:"+stringBuffer.length());    }    private static void update() {        stringBuffer.append("1");    }}//size:5000
StringBuffer每次输入的后果与预期后果统一,因而它是线程平安的类

StringBuffer应用synchronized保障线程平安

 @Override public synchronized StringBuffer append(String str) {   toStringCache = null;   super.append(str);   return this; }

总结

通过以上两个例子能够晓得,StringBuffer为线程安全类,StringBuilder为线程不安全类。

StringBuffer在办法的实现上应用了synchronized关键字对办法进行同步,因而是线程平安的,而StringBuilder则没有进行非凡的同步或并发解决。

StringBuffer应用了同步锁,同一时间只能有一个线程进行拜访,因为在零碎性能会有损耗,实用于多线程环境下应用。通常状况下,字符串拼接呈现在办法内(在办法中以局部变量的形式应用,能够做到线程关闭),应用StringBuilder进行字符串的拼接会大大提高性能,属于堆栈关闭,单个线程的操作对象,因而不存在线程不平安问题,优先选择应用StringBuilder。两种字符串拼接类别离实用不同的场景,这就是为什么JAVA同时提供了这两品种。

关注微信公众号:【入门小站】,解锁更多常识