일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | ||||
4 | 5 | 6 | 7 | 8 | 9 | 10 |
11 | 12 | 13 | 14 | 15 | 16 | 17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 |
25 | 26 | 27 | 28 | 29 | 30 | 31 |
- 제이쿼리그리드
- spring
- JPA
- QueryDSL
- mssql
- 보안
- stream api
- 엑셀 업로드
- DevOps
- rabbitmq
- docker
- 그리드
- Stream
- 스트림
- 자바8
- ci/cd
- sqlserver
- 자동빌드
- Jenkins
- java
- JQuery
- mom
- ORM
- jqGrid
- Javascript
- apache.poi
- 자동배포
- poi
- 대용량 업로드
- MessageQueue
- Today
- Total
개발 메모장
[Java] String, StringBuffer, StringBuilder의 특징 및 차이점 본문
#. 3가지 모두 문자열에 관련되어 저장, 관리를 위한 클래스입니다.
#. 보통 간단한 것에 대해선 String만 사용하는데 상황에 따라 버퍼와 빌더를 사용해야 할 때가 있을 것입니다.
#. String
- 불변성을 가지기에 수정할 수 없고 메모리 할당 공간도 변하지 않습니다.
- 보통 수정하는 것처럼 보이는 작업들은 사실 새로운 String 개체들을 만들어 저장하는 방식으로 진행됩니다.
- 그렇기에 기존 String 개체는 수정되는 것이 아니고, 메모리 할당 공간을 추가로 차지하게 되어 지속적으로 수정 시 성능 저하가 발생할 수 있습니다.
- 주로 간단한 처리에 사용됩니다.(문자 연산 - +, concat() 등)
- 불변성을 가지기에 스레드로부터 안전합니다.
- 수정이 불가하기에 비밀번호 같은 민감 정보 저장에 사용하는 것이 좋습니다.
- Example
String tester = "test";
tester = "tester";
- 문자열 변수 tester는 최초 test라고 되어있고 이를 tester로 수정하였습니다.
- 이 경우 tester = "test"와 tester = "tester" 모두 메모리 상에선 살아있다는 것입니다.
- 기존 tester = "test"는 GC의 제거 대상이 됩니다.
#. StringBuffer
- 가변성을 가지며 새 개체를 생성하지 않고도 문자열을 수정할 수 있는 것이 String과의 가장 큰 차이입니다.
- 멀티스레드 환경에서 동기화를 지원하기 때문에 스레드로부터 안전합니다.
- 경합 조건에 따른 예측불가의 동작
- 공유 데이터, 리소스에 여러 개의 스레드가 접근 시 경합 조건이 달라질 수 있으며, 이에 따라 예측불가한 잘못된 동작이 발생할 수 있습니다.
- 데이터 손상
- 여러 스레드가 동일 데이터에 접근해 수정하려 할 때 잘못된 수정을 초래해 데이터가 불일치하게 되는 경우가 발생할 수 있습니다.
- 동기화로 인해 단일 스레드에선 속도가 느리나 멀티스레드 상황에서 안전하게 사용이 가능합니다.
- Example
- 아래 소스는 멀티스레드 상태에서 하나의 StringBuffer를 수정하는 작업을 합니다.
- thread1과 tread2가 각각 task를 처리하며 각각 A가 1000번씩 더해지므로 thread2가 끝나는 시점엔 length는 2000이 됩니다.
(아래의 StringBuilder와 비교 필수!)
public class StringBufferTester {
private static StringBuffer sbuffer = new StringBuffer();
public static void main(String[] args) {
SpringApplication.run(StringBufferTester.class, args);
Runnable task = () -> {
for (int i = 0; i < 1000; i++) {
sbuffer.append("A");
}
};
Thread thread1 = new Thread(task);
Thread thread2 = new Thread(task);
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Final StringBuffer length: " + sbuffer.length());
}
}
#. StringBuilder
- 가변성을 가지기에 새 객체를 생성하지 않고 수정 가능하나 동기화 지원이 되지 않아 스레드로부터 안전하지 않습니다.
- 비동기적 특성을 지니며 단일스레드에서 가장 성능이 좋습니다.
- 속도는 빠르나 멀티스레드 상황에서 안전하지 않습니다.
- Example
- 위 StringBuffer와 같은 소스이며 StringBuffer 대신 StringBuilder를 사용해 봤습니다.
- append 한 횟수(sbuilder.length)의 값이 초기화한 후 실행 할 때마다 매번 다릅니다.
- thread1과 thread2에 대한 값이 동기화되지 않고 처리되면서 오차가 발생하게 됩니다.
public class StringBuilderTester {
private static StringBuilder sbuilder = new StringBuilder();
public static void main(String[] args) {
SpringApplication.run(StringBuilderTester.class, args);
Runnable task = () -> {
for (int i = 0; i < 1000; i++) {
sbuilder.append("A");
}
};
Thread thread1 = new Thread(task);
Thread thread2 = new Thread(task);
thread1.start();
thread2.start();
try {
thread1.join();
thread2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Final StringBuilder length: " + sbuilder.length());
}
}
#. 정리해 보자면 아래와 같습니다.
- String - 자주 변경하지 않는 객체나 보안에 민감한 데이터에 사용하면 좋습니다.
- StringBuffer - 멀티스레드 환경에서 스레드로부터 안전함을 보장받고자 할 때 사용하면 좋습니다.
- StringBuilder - 단일스레드 환경에서 스레드 이슈 우려가 없고 빠른 성능을 보장받고자 할 때 사용하면 좋습니다.
===========================================================
틀린 내용이 있거나 이견 있으시면 언제든 가감 없이 말씀 부탁드립니다!
===========================================================
'Java' 카테고리의 다른 글
[Java] Stream API(1) - 스트림 데이터 생성 (0) | 2023.12.12 |
---|---|
[Java] Zip 파일 생성 후 파일 다운로드(Ajax 이용) (1) | 2023.12.08 |
[Java] 공공데이터 - 공휴일 API 사용하기 (1) | 2023.12.06 |
[Java] OOM과 GC (Out of Memory Error와 가비지 컬렉터) (1) | 2023.12.04 |
[Java] try with Resources 문(리소스 자동 반환) (2) | 2023.11.27 |