String 과 다른 클래스 비교
String, String Builder, String Buffer 모두 String을 사용하기 위해 사용되는 문자열 클래스들입니다.
이렇게 클래스를 분리해서 사용하는 이유에 대해 알아보겠습니다.
우선 문자열을 할당하고, 해당 문자열을 변경해보겠습니다.
String str = "Hello";
System.out.println("str : "+System.identityHashCode(str));
StringBuilder sb = new StringBuilder("Hello");
System.out.println("sb : "+System.identityHashCode(sb));
StringBuffer sf = new StringBuffer("Hello");
System.out.println("sf : "+System.identityHashCode(sf));
str += " World";
System.out.println(str);
System.out.println("str : "+System.identityHashCode(str));
sb.append(" World");
System.out.println(sb);
System.out.println("sb : "+System.identityHashCode(sb));
sf.append(" World");
System.out.println(sf);
System.out.println("sf : "+System.identityHashCode(sf));
이렇게 전송된 결과의 주소값을 확인해보면
String으로 만든 str값의 주소가 변경되는 것을 알수 있습니다. String이 대표적인 불변객체이기 때문입니다.
즉, String은 불변객체이고 String Builder와 String Buffer는 가변 객체입니다.
String 클래스의 경우 값을 추가하는 것이아니라 기존의 값은 GC에 의해 비워지고, 새로운 값이 재할당이 되는것이죠
하지만 이러한 과정은 전체적인 메모리 공간을 낭비하고, 속도의 지연을 만듭니다.
String Builder와 String Buffer 비교
String Builder와 String Buffer는 사용 문법 자체는 동일합니다. 하지만 동기화라는 부분에서 차이가 생깁니다.
StringBuffer는 스레드에 안전한 프로그램이 필요할 때나, 개발 중인 시스템의 부분이 스레드에 안전한지 모를 경우 사용하면 좋습니다.
StringBuilder는 스레드에 안전한지 여부가 전혀 관계 없는 프로그램을 개발할 때 사용하면 좋습니다.
위 그림처럼 String Builder의 경우에는 멀티스레드 환경에서 동기화를 지원해주지 않기때문에 정보의 정확성을 보장할 수 없습니다. 하지만 String Buffer는 멀티스레드 환경의 동기화를 지원해주기 때문에 어떤 데이터를 사용하는지에 따라서 구분해서 사용하면 될것입니다.
public class Main extends Thread{
public static void main(String[] args) {
StringBuffer stringBuffer = new StringBuffer();
StringBuilder stringBuilder = new StringBuilder();
new Thread(() -> {
for(int i=0; i<10000; i++) {
stringBuffer.append(1);
stringBuilder.append(1);
}
}).start();
new Thread(() -> {
for(int i=0; i<10000; i++) {
stringBuffer.append(1);
stringBuilder.append(1);
}
}).start();
new Thread(() -> {
try {
Thread.sleep(10000);
System.out.println("StringBuffer.length: "+ stringBuffer.length()); // thread safe 함
System.out.println("StringBuilder.length: "+ stringBuilder.length()); // thread unsafe 함
} catch (InterruptedException e) {
e.printStackTrace();
}
}).start();
}
}
이렇게 sleep을 10초로 정하고 20000개의 데이터를 실행시키면
멀티 스레드 환경에 동기화를 보장하는 String Buffer와 String Builder의 차이점을 구분할 수 있습니다.
코드 레벨에서 확인해보면
@Override
public synchronized StringBuffer append(Object obj) {
toStringCache = null;
super.append(String.valueOf(obj));
return this;
}
String Buffer의 경우 append 메소드를 사용할 때 synchronized를 통해 비동기로 동작하기 때문입니다.
따라서 web이나 socket과 같이 비동기로직이 많은 경우에는 String Buffer를 사용해서 처리하는 것이 안전합니다.
총 정리
단순히 객체의 연산이 적다면 String이 가장 좋도, 검색속도도 빠릅니다.
하지만 객체의 연산이 많다면 메모리 용량을 적게 사용하는 String Buffer나 String Builder에 대해 고려하게 됩니다.
Stirng Builder가 단순 속도는 빠르지만, 단일 스레드의 경우 문제가 생기지 않습니다.
하지만 멀티 스레드 환경을 고려해야되는 상황이라면, 정확성을 위해서 String Buffer를 사용해줘야 합니다.
(현업의 코드는 대부분 멀티 스레드 환경에서 구축되므로 StirngBuffer로 통일하면 됩니다.)
참고 :
'기술 스텍 > Java' 카테고리의 다른 글
Call By Value와 Call By Reference 차이점 분석 (0) | 2024.01.20 |
---|---|
JVM 내부 구조 정리 (1) | 2024.01.14 |
고유 락이란? -Java (0) | 2024.01.08 |
[Java] 가비지 컬렉션이란? (0) | 2024.01.07 |
[Collection] ArrayList를 왜 List로 받아야 하는가? List의 종류 (0) | 2023.06.24 |