Java에서는 문자열을 다루기 위한 다양한 클래스가 제공되는데, 가장 대표적인 것이 String, StringBuilder, 그리고 StringBuffer입니다. 가지 클래스는 모두 문자열을 다루지만, 변경 가능성(Mutability) 스레드 안전성(Thread Safety) 측면에서 차이가 있습니다.

 

String 클래스

String 클래스는 불변(Immutable) 객체로, 한 번 생성된 문자열은 수정할 수 없습니다. 문자열이 변경될 때마다 새로운 String 객체가 생성됩니다.

 

특징

  • 불변성: String은 한 번 생성되면 내용을 변경할 수 없습니다.
  • 새로운 객체 생성: 문자열을 조작할 때마다 새로운 객체가 생성되므로 문자열을 자주 변경하는 경우 메모리 효율이 떨어질 수 있습니다.
  • 리터럴 활용: String 객체는 String Pool에 저장되어, 동일한 리터럴 값이 있을 경우 같은 객체를 공유합니다.
String str = "Hello";
str = str + " World"; // 새로운 객체가 생성됨

 

StringBuilder 클래스

StringBuilder 클래스는 가변(Mutable) 객체로, 문자열을 직접 변경할 수 있습니다. 하지만 StringBuilder 클래스는 스레드 안전성을 제공하지 않기 때문에, 멀티 스레드 환경에서 문자열을 조작할 때 동시성 이슈가 발생할 수 있습니다.

 

특징

  • 가변성: 문자열을 조작할 때 동일 객체 내에서 변경됩니다.
  • 성능 우수: String에 비해 메모리 효율이 높고, 속도가 빠릅니다.
  • 스레드 안전성 미제공: 여러 스레드에서 동시에 접근할 경우, 안전하지 않을 있습니다.
StringBuilder sb = new StringBuilder("Hello");
sb.append(" World"); // 같은 객체 내에서 문자열이 변경됨
System.out.println(sb.toString()); // "Hello World" 출력

 

StringBuffer 클래스

StringBuffer는 StringBuilder와 유사하게 가변 객체이지만, **스레드 안전(Thread-Safe)**합니다. 모든 메서드가 동기화(Synchronized) 되어 있어, 여러 스레드에서 접근해도 안전하게 사용할 수 있습니다. 다만, 이로 인해 StringBuilder보다 속도가 약간 느립니다.

 

특징

  • 가변성: StringBuilder와 동일하게 같은 객체 내에서 문자열을 변경합니다.
  • 스레드 안전성 제공: 메서드가 동기화되어 있어, 멀티스레드 환경에서도 안전하게 사용할 수 있습니다.
  • 성능: 스레드 동기화 처리로 인해 StringBuilder보다 느리지만, String보다는 성능이 좋습니다.
StringBuffer sbf = new StringBuffer("Hello");
sbf.append(" World"); // 같은 객체 내에서 문자열이 변경됨
System.out.println(sbf.toString()); // "Hello World" 출력

 

멀티쓰레드 환경 StringBuilder, StringBuffer 테스트

StringBuilderStringBuffer를 각각 2개의 스레드를 생성하여 "A" 문자열을 100000번씩 append하는 테스트 코드입니다.

100000번씩 두 번 더했기 때문에 문자열 길이가 200000이 나오는 것을 예상했지만 StringBuilder는 멀티쓰레드 환경에서 안전성을 보장하지 않기 때문에 기대한 값이 나오지 않았고 StringBuffer는 기대한 값이 나와 테스트를 통과한 것을 확인할 수 있습니다.

또한 실행 시간을 측정한 결과 동기화 처리로 인해 StringBuffer 속도가 41ms로 StringBuilder보다 오래 걸린 것을 확인할 수 있습니다.

@SpringBootTest
public class TestClass {

    @Test
    public void stringBuilderTest() {
        StringBuilder sharedBuilder = new StringBuilder();

        Runnable task = () -> {
            for (int i = 0; i < 100000; i++) {
                sharedBuilder.append("A");
            }
        };

        // 두 개의 스레드가 동일한 StringBuilder 인스턴스를 동시에 수정
        Thread thread1 = new Thread(task);
        Thread thread2 = new Thread(task);

        long startTime = System.currentTimeMillis();
        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();

        // 실행 시간 계산 및 출력
        long executionTime = endTime - startTime;
        System.out.println("StringBuilder Thread execution time: " + executionTime + " ms"); // 4ms
        Assertions.assertNotEquals(200000, sharedBuilder.length());
    }

    @Test
    public void stringBufferTest() {
        StringBuffer sharedBuffer = new StringBuffer();

        Runnable task = () -> {
            for (int i = 0; i < 100000; i++) {
                sharedBuffer.append("A");
            }
        };

        // 두 개의 스레드가 동일한 StringBuilder 인스턴스를 동시에 수정
        Thread thread1 = new Thread(task);
        Thread thread2 = new Thread(task);

        long startTime = System.currentTimeMillis();
        thread1.start();
        thread2.start();

        try {
            thread1.join();
            thread2.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        long endTime = System.currentTimeMillis();

        // 실행 시간 계산 및 출력
        long executionTime = endTime - startTime;
        System.out.println("StringBuffer Thread execution time: " + executionTime + " ms"); // 41ms
        Assertions.assertEquals(200000, sharedBuffer.length());
    }
}

 

String, StringBuilder, StringBuffer 비교

구분 String StringBuilder StringBuffer
변경 가능성 불변 (Immutable) 가변 (Mutable) 가변 (Mutable)
스레드 안전성 안전하지 않음 안전하지 않음 스레드 안전 (Synchronized)
속도 가장 느림 가장 빠름 StringBuilder보다 느림
사용 환경 변경이 필요 없는 문자열 단일 스레드에서 자주 변경하는 문자열 멀티스레드에서 자주 변경하는 문자열

 

+ Recent posts