본문 바로가기

JAVA

String , StringBuilder, StringBuffer 속도차이 비교

이전에 쓰레드에 관련하여 포스팅한 자료가 있는데, 마지막에 언급하였던 StringBuilder 와 StringBuffer 의 성능차이가 어느정도로 나는지 궁금하여 포스팅 하게되었다.

 

실험해보는김에 String도 같이 해보고자 한다.

 

쓰레드(3) - Synchronized

 

쓰레드(3) - Synchronized

1. 쓰레드와 밀접한 연관이 있는 Synchronized synchronized는 자바의 예약어 중 하나이다. 즉, 변수명, 클래스명으로 사용이 불가능하다. StringBuffer와 StringBuilder의 차이점으로 StringBuffer는 "쓰레드에..

dev-cool.tistory.com

 

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);
        }

    }
}

StringBuffer 사용시
StringBuilder 사용시

확실히 String의 연산속도에비해 두 클래스는 빠른 성능을 보여주었다.

 

그 이유는 String은 불변객체이기 때문에 +연산을 하는 경우 객체에 값을 변경하는것이 아니라. 새로운 객체를 생성해서 참조하는 것이기 때문이다.

 

불변객체(Immutable Object)를 사용해야하는 이유

 

불변객체(Immutable Object)를 사용해야하는 이유

1. 불변객체(Immutable Object)란? 불변객체는 말그대로 변하지않는 객체로 객체가 생성된후 내부 상태가 변하지 않는 객체를 의미한다. 불변객체는 Setter 메소드를 제공하지 않으며, 내부상태를 제공

dev-cool.tistory.com

 

하지만 이론상으로는 두 클래스는 성능상의 차이가 있다고 알고있었는데 막상 그렇게 많은 성능차이는 안나는것 같아서

반복문의 횟수를 증가시켜보았다.

 

StringBuffer 사용시
StringBuilder 사용시

 

반복문 횟수를 2자리수늘려서 실행해본 결과 확실히 StringBuilder를 사용했을때 빠른성능을 보여주는것을 알수있다.