StringBuilder와 StringBuffer 비교

suebeen·2021년 8월 8일
0

Java

목록 보기
5/7
post-thumbnail

자바에서 String과 StringBuilder, StringBuffer의 차이는 무엇일까?

String

자바는 문자열을 사용할 수 있도록 String 클래스를 제공한다.

String을 사용할 때 문자열을 생성자의 매개변수로 하여 생성하는 방식과 이미 생성된 문자열 상수를 가리키는 방식이 있다.

String s1 = "Hello World"; 
String s2 = new String("Hello World"); 

new 예약어를 사용하여 객체를 사용하는 경우 "abc" 문자열을 위한 메모리가 할당되고 새로운 객체가 생성된다.

하지만 생성자를 이용하지 않고 바로 문자열 상수를 가리키는 경우에는 기존에 만들어져 있던 "test"라는 문자열 상수의 메모리 주소를 가리키게 된다.

이 변수는 final로 선언되어있기 때문에 String은 불변이다. 한 번 생성하게 되면 변경할 수 없다.

만약 문자열을 연결하려고 하면 둘 중 하나의 문자열이 변경되는 것이 아니라 두 문자열이 연결된 새로운 문자열이 생성된다.

StringBuilder와 StringBuffer

프로그램을 만들다 보면 문자열을 변경하거나 연결해야 할 때가 많은데 String 클래스를 사용하여 문자열을 변경하게 되면 메모리가 많이 낭비된다. 이 문제를 해결하는 것이 바로 StringBuilder와 StringBuffer 클래스다.

불변인 String과 달리 StringBuilder와 StringBuffer는 가변의 속성을 가지고 있다.

두 클래스는 final이 아닌 char[]를 변수로 가지고 있다. 따라서 두 문자열을 연결하게 되면 기존에 사용하던 char[] 배열에 확장되므로 추가 메모리를 사용하지 않는다.

그렇다면 두 클래스의 차이는 무엇일까?

두 클래스의 차이는 바로 스레드 동기화의 안전성을 보장하느냐, 보장하지 않느냐의 차이다.

StringBuffer 클래스는 문자열이 안전하게 변경되도록 보장하지만, StringBuilder 클래스는 보장되지 않는다.

@Override
public synchronized StringBuffer append(Object obj) {
	toStringCache = null;
	super.append(String.valueOf(obj));
	return this;
}
@Override
public StringBuilder append(Object obj) {
	return append(String.valueOf(obj));
}

두 클래스를 봤을 때 StringBuffer의 append앞에는 syschronized가 붙어있는 것을 확인할 수 있다.

자바에서 지원하는 Synchronized 키워드는 여러개의 스레드가 한개의 자원을 사용하고자 할 때, 현재 데이터를 사용하고 있는 해당 스레드를 제외하고 나머지 스레드들은 데이터에 접근 할 수 없도록 막는 개념이다.

성능 비교

package String;

// String, StringBuilder, StringBuffer의 성능 비교 테스트
public class StringTest {
    private static final int MAX_LOOP_COUNT = 100000;
    public static void main(String[] args) {

        // String
        String str = "";
        MyClock stringClock = new MyClock();
        stringClock.startClock();
        for (int i = 0; i < MAX_LOOP_COUNT; i++) {
            str += i + "@";
        }
        stringClock.stopClock();
        stringClock.printResult("String");


        // StringBuilder
        StringBuilder builder = new StringBuilder();
        MyClock builderClock = new MyClock();
        builderClock.startClock();
        for (int i = 0; i < MAX_LOOP_COUNT; i++) {
            builder.append(i).append("@");
        }
        builderClock.stopClock();
        builderClock.printResult("StringBuilder");


        // StringBuffer
        StringBuffer buffer = new StringBuffer();
        MyClock bufferClock = new MyClock();
        bufferClock.startClock();
        for (int i = 0; i < MAX_LOOP_COUNT; i++) {
            buffer.append(i).append("@");
        }
        bufferClock.stopClock();
        bufferClock.printResult("StringBuffer");

    }
}


멀티스레드 프로그램이 아니라면 StringBuilder를 사용하는 것이 실행 속도가 더 빠르다.

참고
https://madplay.github.io/post/difference-between-string-stringbuilder-and-stringbuffer-in-java

0개의 댓글