面试题答案
一键面试合理设置初始容量
在使用StringBuffer
时,合理设置初始容量可以减少动态扩容带来的性能开销。如果预估日志记录的字符串长度,可将该长度作为StringBuffer
构造函数的参数来设置初始容量。例如,如果预估日志字符串长度大约为1000个字符,可以这样创建StringBuffer
:
StringBuffer sb = new StringBuffer(1000);
避免不必要的同步
StringBuffer
是线程安全的,方法都使用synchronized
关键字修饰。然而,在多线程日志记录系统中,如果每个线程独立使用自己的StringBuffer
实例,就可以避免不必要的同步开销。可以使用ThreadLocal
来为每个线程提供独立的StringBuffer
实例。
代码示例
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class MultithreadedLoggingSystem {
// 使用ThreadLocal为每个线程提供独立的StringBuffer实例
private static final ThreadLocal<StringBuffer> threadLocalBuffer = ThreadLocal.withInitial(() -> new StringBuffer(1000));
public static void main(String[] args) {
ExecutorService executorService = Executors.newFixedThreadPool(10);
for (int i = 0; i < 10; i++) {
executorService.submit(() -> {
StringBuffer sb = threadLocalBuffer.get();
sb.append("Thread ").append(Thread.currentThread().getName()).append(" is logging...\n");
// 这里可以继续追加更多日志内容
System.out.println(sb.toString());
// 清理ThreadLocal中的StringBuffer,避免内存泄漏
threadLocalBuffer.remove();
});
}
executorService.shutdown();
}
}
在上述代码中:
- 使用
ThreadLocal<StringBuffer>
为每个线程提供独立的StringBuffer
实例,避免了多线程环境下的同步开销。 - 为
StringBuffer
设置了初始容量1000,减少动态扩容的性能损耗。 - 在使用完
StringBuffer
后,通过threadLocalBuffer.remove()
方法清理ThreadLocal
中的实例,防止内存泄漏。