string, stringbuffer, stringbuilder

박영준·2023년 3월 15일
0

Java

목록 보기
49/111

Java 에서 문자열을 다루는 클래스에는 대표적으로 String, StringBuffer, StringBuilder 가 있다.

연산이 많지 않을 때는 어떤 클래스를 사용하더라도 무방하나,
연산 횟수가 많을 때 or 멀티쓰레드 or Race condition 인 상황이 자주 발생 시 적절한 클래스의 사용이 필요하다.

Race condition
두 개 이상의 프로세스가 공통 자원을 병행적으로(concurrently) 읽거나 쓰는 동작을 할 때,
공용 데이터에 대한 접근이 어떤 순서에 따라 이루어졌는지에 따라 그 실행 결과가 같지 않고 달라지는 상황
(두 개의 스레드가 하나의 자원을 놓고 서로 사용하려고 경쟁)

1. String, StringBuffer/StringBuilder

1) String

불변성 immutable

String str = "hello";   // String str = new String("hello");
str = str + "world";  // [ hello world ]

(1) 잘못된 해석

: String 의 str 변수에 "hello" 이 저장돼있고, 여기에 "world"를 더하면 "hello world" 가 된다.

(2) 올바른 해석

String 클래스의 참조변수 str 에는 "hello" 이 들어가 있는 상태였다.

그리고 str 이 "hello world" 값을 가지게 되면
새로운 메모리영역을 가리키게 되고, 처음에 선언헀던 메모리 영역("hello"로 값이 할당되어 있던)은 Garbage로 남아있다가 GC(garbage collection)에 의해 사라진다.

즉, String 클래스의 불변성으로 인해, 문자열을 수정하는 시점에 새로운 String 인스턴스가 생성된 것이다.

장점

변하지 않는 문자열을 자주 읽어들이는 경우, 성능을 향상시킬 수 있다.

단점

문자열의 연산(추가/수정/삭제 등...) 자주 발생하는 알고리즘에서는 힙 메모리(Heap)에 많은 임시 가비지(Garbage)가 생성되어,
힙 메모리 부족으로 어플리케이션 성능에 치명적인 영향을 끼치게 된다.

2) StringBuffer/StringBuilder

가변성 mutable

String 의 불변성이 가지는 문제점을 해결하기 위해 등장했다.

StringBuffer sb= new StringBuffer("hello");
sb.append(" world");

.append() .delete() 등의 API를 이용하여 동일 객체내에서 문자열을 변경하는 것이 가능하다.
따라서, 문자열의 연산(추가/수정/삭제 등...) 자주 발생할 경우, StringBuffer/StringBuilder 를 사용해야 한다.

주의!
'String 의 불변성'이란 배열 안에 '내용'을 변경할 수 없다는 의미다.

String 과 StingBuffer 모두 배열의 길이를 자동적으로 변경할 수는 없다.

String 과 StingBuffer 의 공통점

public final class StringBuffer {
	private char[] value;
}
  • String 또는 StringBuffer 인스턴스가 생성될 때, char형 배열이 생성된다.
  • 문자열을 저장하기 위한 char형 배열의 참조변수를 인스턴스로 선언해둔다.

2. StringBuffer, StringBuilder

1) StringBuffer

참고: StringBuffer 클래스

동기화 O

  • 멀티쓰레드 환경에서 안전(thread-safe)하도록 동기화 되어있음
    (String도 불변성으로 인해, 멀티쓰레드 환경에서의 안정성(thread-safe)을 가진다)

  • 동기화는 StringBuffer 의 성능을 떨어뜨린다

2) StringBuilder

동기화 X

  • 멀티쓰레드 환경에서의 사용은 부적합하지만, 동기화를 고려하지 않는 만큼 단일 쓰레드에서의 성능은 StringBuffer 보다 뛰어나다.

  • StringBuffer 에서 쓰레드의 동기화만 뺀 것이 StringBuilder

    • StringBuffer 와 완전 동일한 기능을 가진다

      • 따라서, StringBuffer -> StringBuilder 로 변경하고 싶다면, 이 두 부분만 변경하면 된다.

        // StringBuffer 를 사용할 경우
        StringBuffer sb = new StringBuffer();		// StringBuffer 타입의 참조변수 선언 & 생성자
        sb.append("abc");
        
        // StringBuilder 를 사용할 경우
        StringBuilder sb = new StringBuilder();
        sb.append("abc");
        • StringBuffer 타입의 참조변수 선언
        • StringBuffer 생성자

3. 결론

10만번 이상의 연산 시,
String 객체는 수행시간이 기하급수적으로 늘어나지만
StringBuilder와 StringBuffer는 1000만번까지 버티며
그 이상은 StringBuilder가 우월하다.

따라서, 싱글 쓰레드 환경에서나 비동기를 사용할 일이 없으면, StringBuilder를 쓰는 것이 이상적이다.

주의!
현업에서는 대부분 멀티 스레드 이상의 환경에서 자바 어플리케이션을 돌리기 때문에,
왠만하면 안정적인 StringBuffer로 통일하여 코딩하는것이 좋다.
(사실, StringBuffer 와 StringBuilder 속도 차이는 거의 미미하다)


참고: [운영체제] Race Condition과 예방할 방법(세마포어, 뮤텍스)
참고: [Java] String, StringBuffer, StringBuilder 차이 및 장단점
참고: [Java] String, StringBuffer, StringBuilder의 차이점과 사용이유
참고: [JAVA] ☕ String / StringBuffer / StringBuilder 차이점 & 성능 비교

profile
개발자로 거듭나기!

0개의 댓글