이전에 쓰레드에 관련하여 포스팅한 자료가 있는데, 마지막에 언급하였던 StringBuilder 와 StringBuffer 의 성능차이가 어느정도로 나는지 궁금하여 포스팅 하게되었다.
실험해보는김에 String도 같이 해보고자 한다.
1. String
먼저 String 변수를 하나 만들고 += 연산을 사용해서 문자열의 +연산이 어느정도 걸리는지 측정해보자
public class CompareTime {
public static void main(String[] args) {
for (int i = 0; i < 10; i++){
String str = "";
//시작시간
long beforeTime = System.nanoTime();
for(int j = 0; j<10000; j++){
str += "cool";
}
//종료시간
long afterTime = System.nanoTime();
System.out.println((afterTime-beforeTime)/1000.0);
}
}
}
시간을 System.nanoTime()을 사용해서 계산한 이유는
System.currentTimeMillis() 을 먼저 사용했는데 StringBuilder와 StringBuffer의 시간비교가 어려워서 사용했다.
2. StringBuilder vs StringBuffer
이전포스팅에서 언급한것 처럼 StringBuffer 클래스는 동기화처리가 되어 쓰레드에 안전하지만 그만큼 여러 쓰레드가 접근하는 경우 Lock이 걸릴 확률이 있기때문에 StringBuilder에 비해 성능이 좋지 않다.
반대로 StringBuilder 클래스는 동기화처리가 되어있지 않아서 성능상에 장점은 있지만 멀티 쓰레드 환경에서는 안전하지 못하다.
StringBuilder 와 StringBuffer 클래스 내부로 들어가서 동작하는 구조를 파악해보자.
public final class StringBuffer
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{
...
@Override
public synchronized StringBuffer append(String str) {
toStringCache = null;
super.append(str);
return this;
}
...
}
public final class StringBuilder
extends AbstractStringBuilder
implements java.io.Serializable, CharSequence
{
...
@Override
public StringBuilder append(String str) {
super.append(str);
return this;
}
...
}
직접 내부 구조를 살펴보게 되면 StringBuffer 의 경우 메소드가 synchronized 로 처리되어 있어서 동기화 하는 반면
StringBuilder 의 경우 메소드가 동기화 처리 되지 않은것을 확인할 수 있다.
두 클래스를 직접 사용해서 비교해보자.
public class CompareTime {
public static void main(String[] args) {
for (int i = 0; i < 10; i++){
StringBuffer str = new StringBuffer();
//StringBuilder str = new StringBuilder();
//시작시간
long beforeTime = System.nanoTime();
for(int j = 0; j<10000; j++){
str.append("cool");
}
//종료시간
long afterTime = System.nanoTime();
System.out.println((afterTime-beforeTime)/1000000.0);
}
}
}
확실히 String의 연산속도에비해 두 클래스는 빠른 성능을 보여주었다.
그 이유는 String은 불변객체이기 때문에 +연산을 하는 경우 객체에 값을 변경하는것이 아니라. 새로운 객체를 생성해서 참조하는 것이기 때문이다.
불변객체(Immutable Object)를 사용해야하는 이유
하지만 이론상으로는 두 클래스는 성능상의 차이가 있다고 알고있었는데 막상 그렇게 많은 성능차이는 안나는것 같아서
반복문의 횟수를 증가시켜보았다.
반복문 횟수를 2자리수늘려서 실행해본 결과 확실히 StringBuilder를 사용했을때 빠른성능을 보여주는것을 알수있다.
'JAVA' 카테고리의 다른 글
Volatile 을 사용한 가시성 보장 (0) | 2022.03.15 |
---|---|
쓰레드의 지역변수 ThreadLocal (0) | 2022.03.15 |
일급 컬렉션 (First Class Collection) 을 사용하자 (0) | 2022.03.01 |
Equals 와 HashCode (0) | 2022.02.09 |
방어적 복사 vs Unmodifiable Collection (0) | 2022.02.08 |
자바의 예외구분 Checked Exception, Unchecked Exception (0) | 2022.02.08 |