乐趣区

关于多线程:StringBuilder与StringBuffer

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 同时提供了这两品种。

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

退出移动版