StringBuilder性能优化

    String是不可变的,每次对字符串进行拼接都会创建一个新的String对象,这可能导致频繁的内存分配和垃圾回收。为了避免这种情况,我们可以使用StringBuilder(如果需要线程安全性用StringBuffer)来执行大量的字符串拼接操作。

    StringBuilder虽然在字符串拼接时,性能已经比String拼接优异很多了,但我们依然可以从三个方面来对StringBuilder进行性能优化。     

  • StringBuilder默认容量是16,当我们拼接多个字符串,会进行扩容以及复制字符数组操作。
  • 当高并发,频繁地创建StringBuilder对象也是会导致频繁的内存分配和垃圾回收。
  • StringBuilder本身是线程不安全的,我们可以通过ThreadLocal,来让它进行线程隔离。

 StringBuilder扩容代码:

对StringBuilder进行优化,提出一个StringBuilderHelper类,提供优化后的接口。

public class StringBuilderHelper {
	//由于StringBuilder不是线程安全的,用ThreadLocal来进行线程隔离
	private static ThreadLocal<StringBuilder> stringBuilderLocal = new ThreadLocal<StringBuilder>() {
		@Override
		protected StringBuilder initialValue() {
			//根据业务需求,给定一个合适的初始capacity
			//尽量避免后续扩容
			//也避免给太大容量,浪费空间
			return new StringBuilder(4096);
		}
	};
	
	public static StringBuilder getBuilder(){
		StringBuilder stringBuilder = stringBuilderLocal.get();
		if(stringBuilder.capacity() > 16384){
			//当StringBuilder已经扩容到了一定值(这个值根据业务来定)
			//使用一个新的初始容量的StringBuilder
			stringBuilder = new StringBuilder(4096);
			//更新ThreadLocal
			stringBuilderLocal.set(stringBuilder);
		}else{
			//重置length,实现对StringBuilder的复用
			stringBuilder.setLength(0);
		}
		return stringBuilder;
	}
}

测试代码: 

public static void main(String[] args) {
		CyclicBarrier cyclicBarrier = new CyclicBarrier(2);
		Thread thread1 = new Thread(() -> {
			try {
				cyclicBarrier.await();//保证两个线程同时执行
				System.out.println("Thread1开始执行");
				//线程间StringBuilder隔离
				StringBuilder stringBuilder = StringBuilderHelper.getBuilder();
				stringBuilder.append("a").append("c").append("b");
				System.out.println("Thread1:" + stringBuilder.toString());
				//线程内StringBuilder复用
				stringBuilder = StringBuilderHelper.getBuilder();
				stringBuilder.append("d").append("e").append("f");
				System.out.println("Thread1:" + stringBuilder.toString());
			} catch (Exception e) {
			}
		});
		Thread thread2 = new Thread(() -> {
			try {
				cyclicBarrier.await();//保证两个线程同时执行
				System.out.println("Thread2开始执行");
				//线程间StringBuilder隔离
				StringBuilder stringBuilder = StringBuilderHelper.getBuilder();
				stringBuilder.append("o").append("p").append("q");
				System.out.println("Thread2:" + stringBuilder.toString());
				//线程内StringBuilder复用
				stringBuilder = StringBuilderHelper.getBuilder();
				stringBuilder.append("r").append("s").append("t");
				System.out.println("Thread2:" + stringBuilder.toString());
			} catch (Exception e) {
			}
		});
		thread1.start();
		thread2.start();
	}

测试结果:

 

通过结果可以看出,不用重复地去new StringBuilder,就能实现StringBuilder线程内复用,线程间隔离。

  • 11
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值