關注微信公眾號 架構技術之美 ,學習更多技術和學習資料。
String 是
不可變物件
,每次對 String 物件進行改變都會生成一個新的 String 物件,然後將指標指向新的 String 物件,故經常改變內容的字串最好不要用 String 。因為每次生成物件都會對系統效能產生影響,特別當記憶體中無參照物件多了以後, JVM 的 GC 就會開始工作,那速度就更加慢了。
package com.nobody.part01;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
* @author Mr.nobody
* @Description 測試String字串拼接效能
* @date 2020/9/17
*/
public class StringDemo {
// 請求總數
private static int CLIENT_COUNT = 10000;
// 並行執行緒數
private static int THREAD_COUNT = 500;
// 全域性變數
private static String STRING = new String();
public static void main(String[] args) throws InterruptedException {
// 固定執行緒池
ExecutorService executorService = Executors.newFixedThreadPool(CLIENT_COUNT);
// 控制同一個時刻,只能有多少個執行緒同時執行指定程式碼,即acquire和release之間的程式碼
Semaphore semaphore = new Semaphore(THREAD_COUNT);
CountDownLatch countDownLatch = new CountDownLatch(CLIENT_COUNT);
long startTime = System.currentTimeMillis();
for (int i = 0; i < CLIENT_COUNT; i++) {
executorService.execute(() -> {
try {
semaphore.acquire();
STRING += "0";
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
countDownLatch.countDown();
}
});
}
// 等待所有請求執行完
countDownLatch.await();
// 關閉執行緒池
executorService.shutdown();
long endTime = System.currentTimeMillis();
System.out.println("String -- 總共耗時:" + (endTime - startTime) + "ms,字串長度:" + STRING.length());
}
}
StringBuffer 是
可變物件
,每次對 StringBuffer 物件進行改變都會對StringBuffer 物件本身進行操作。而不是生成新的物件,再改變物件參照。如果 StringBuffer 物件在多執行緒環境下,特別是字串物件經常改變的情況下,推薦使用它 。因為 StringBuffer 幾乎所有的方法都加了synchronized關鍵字,所以是執行緒安全的,但是效能會相對較差。
package com.nobody.part01;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
* @author Mr.nobody
* @Description 測試執行緒安全類StringBuffer
* @date 2020/9/17
*/
public class StringBufferDemo {
// 請求總數
private static int CLIENT_COUNT = 10000;
// 並行執行緒數
private static int THREAD_COUNT = 500;
// 全域性變數,執行緒安全StringBuffer
private static StringBuffer STRINGBUFFER = new StringBuffer();
public static void main(String[] args) throws InterruptedException {
// 固定執行緒池
ExecutorService executorService = Executors.newFixedThreadPool(CLIENT_COUNT);
// 控制同一個時刻,只能有多少個執行緒同時執行指定程式碼,即acquire和release之間的程式碼
Semaphore semaphore = new Semaphore(THREAD_COUNT);
CountDownLatch countDownLatch = new CountDownLatch(CLIENT_COUNT);
long startTime = System.currentTimeMillis();
for (int i = 0; i < CLIENT_COUNT; i++) {
executorService.execute(() -> {
try {
semaphore.acquire();
STRINGBUFFER.append("0");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
countDownLatch.countDown();
}
});
}
// 等待所有請求執行完
countDownLatch.await();
// 關閉執行緒池
executorService.shutdown();
long endTime = System.currentTimeMillis();
System.out.println("StringBuffer -- 總共耗時:" + (endTime - startTime) + "ms,字串長度:" + STRINGBUFFER.length());
}
}
StringBuilder 一個
可變的字元序列
。StringBuilder 提供一個與 StringBuffer 相容的 API,但不保證同步(即執行緒不安全
)。該類被設計用作 StringBuffer 的一個簡易替換,用在字串緩衝區被單個執行緒使用的時候(這種情況很普遍)
。在堆疊封閉等執行緒安全的環境下(方法中的區域性變數)應該首選 StringBuilder。
package com.nobody.part01;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Semaphore;
/**
* @author Mr.nobody
* @Description 測試執行緒不安全類StringBuilder
* @date 2020/9/17
*/
public class StringBuilderDemo {
// 請求總數
private static int CLIENT_COUNT = 10000;
// 並行執行緒數
private static int THREAD_COUNT = 500;
// 全域性變數,執行緒不安全StringBuilder
private static StringBuilder STRINGBUILDER = new StringBuilder();
public static void main(String[] args) throws InterruptedException {
// 固定執行緒池
ExecutorService executorService = Executors.newFixedThreadPool(CLIENT_COUNT);
// 控制同一個時刻,只能有多少個執行緒同時執行指定程式碼,即acquire和release之間的程式碼
Semaphore semaphore = new Semaphore(THREAD_COUNT);
CountDownLatch countDownLatch = new CountDownLatch(CLIENT_COUNT);
long startTime = System.currentTimeMillis();
for (int i = 0; i < CLIENT_COUNT; i++) {
executorService.execute(() -> {
try {
semaphore.acquire();
STRINGBUILDER.append("0");
semaphore.release();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
countDownLatch.countDown();
}
});
}
// 等待所有請求執行完
countDownLatch.await();
// 關閉執行緒池
executorService.shutdown();
long endTime = System.currentTimeMillis();
System.out.println("StringBuilder -- 總共耗時:" + (endTime - startTime) + "ms,字串長度:" + STRINGBUILDER.length());
}
}