답변:
StringBuffer
동기화 StringBuilder
되지 않습니다.
StringBuilder
StringBuffer
그렇지 않기 때문에 보다 빠릅니다.synchronized
.
간단한 벤치 마크 테스트는 다음과 같습니다.
public class Main {
public static void main(String[] args) {
int N = 77777777;
long t;
{
StringBuffer sb = new StringBuffer();
t = System.currentTimeMillis();
for (int i = N; i --> 0 ;) {
sb.append("");
}
System.out.println(System.currentTimeMillis() - t);
}
{
StringBuilder sb = new StringBuilder();
t = System.currentTimeMillis();
for (int i = N; i > 0 ; i--) {
sb.append("");
}
System.out.println(System.currentTimeMillis() - t);
}
}
}
테스트 실행은 의 수를 제공 2241 ms
하기위한 StringBuffer
대 753 ms
를위한 StringBuilder
.
--> 0
루프에서 처음으로 본 것입니다 . 그것이 무엇을 의미하는지 깨달을 순간을 얻었습니다. 이것이 일반적인 ...; i > 0; i--
구문 대신 실제로 실제로 사용되는 것 입니까?
i -->
문법적으로 정말 성가신 일입니다 ... ASCII 아트에 대한 의견 때문에 처음에는 화살표라고 생각했습니다.
main()
또한 벤치 마크는 불공평합니다. 워밍업이 없습니다.
기본적으로 StringBuffer
메소드는 동기화 StringBuilder
되지 않은 상태에서 동기화 됩니다.
작업은 "거의"동일하지만 단일 스레드에서 동기화 된 메소드를 사용하는 것은 과도합니다.
그것은 거의 그것에 관한 것입니다.
StringBuilder API 에서 인용 :
이 클래스 [StringBuilder]는 StringBuffer와 호환되는 API를 제공 하지만 동기화를 보장하지는 않습니다 . 이 클래스는 문자열 버퍼가 단일 스레드에 의해 사용되는 장소에서 StringBuffer를 대체하는 대체물로 사용하도록 설계되었습니다 (일반적인 경우). 가능한 경우이 클래스 는 대부분의 구현에서 더 빠를 것이기 때문에 StringBuffer 보다 우선적으로 사용하는 것이 좋습니다 .
그래서 그것을 대체하기 위해 만들어졌습니다.
동일은 무슨 일이 있었 Vector
하고 ArrayList
.
Hashtable
와 HashMap
.
그러나 예제의 도움으로 명확한 차이를 얻어야합니까?
StringBuffer 또는 StringBuilder
StringBuilder
스레드간에 버퍼를 실제로 공유하지 않는 한 간단하게 사용하십시오 . StringBuilder
원래 동기화 StringBuffer
클래스 의 동기화되지 않은 (더 적은 오버 헤드 = 더 효율적인) 남동생 입니다.
StringBuffer
먼저왔다. Sun은 모든 조건에서 정확성에 관심을 가졌기 때문에 만일의 경우를 대비하여 스레드 안전을 위해 동기화했습니다.
StringBuilder
나중에왔다. 대부분의 용도 StringBuffer
는 단일 스레드이며 불필요하게 동기화 비용을 지불했습니다.
이후 StringBuilder
A는 드롭 인 교체 용은StringBuffer
동기가없는 모든 실시 예 사이의 차이가 없을 것이다.
당신이하면 되는 스레드간에 공유에 노력하고, 당신이 사용할 수있는 StringBuffer
, 그러나 아마 대신 StringBuffer를 사용의 예를 들면, 높은 레벨의 동기화가 필요한지 여부를 고려, 당신은 모두 StringBuilder를 사용하는 방법을 동기화해야합니다.
먼저 유사점을 살펴 보겠습니다. StringBuilder와 StringBuffer는 모두 변경 가능합니다. 즉, 동일한 위치에서 컨텐츠를 변경할 수 있습니다.
차이점 : StringBuffer도 변경 가능하고 동기화됩니다. StringBuilder는 변경 가능하지만 기본적으로 동기화되지 않습니다.
동기화의 의미 (동기화) : 어떤 것이 동기화되면 여러 스레드가 액세스하여 문제 또는 부작용없이 스레드를 수정할 수 있습니다. StringBuffer는 동기화되어 있으므로 아무 문제없이 여러 스레드에서 사용할 수 있습니다.
언제 어느 것을 사용해야합니까? StringBuilder : 수정할 수있는 문자열이 필요한 경우 하나의 스레드 만 액세스하고 수정합니다. StringBuffer : 수정이 가능한 문자열이 필요하고 여러 스레드가 액세스하고 수정하는 경우.
참고 : 불필요하게 StringBuffer를 사용하지 마십시오. 즉, 하나의 스레드 만 수정하고 액세스하는 경우 동기화에 대한 잠금 및 잠금 해제 코드가 많아 CPU 시간이 불필요하게 걸리므로 사용하지 마십시오. 필요한 경우가 아니면 잠금을 사용하지 마십시오.
단일 스레드에서 StringBuffer는 StringBuilder보다 크게 느리지 않습니다. JVM 최적화 덕분에 . 그리고 멀티 스레딩에서는 안전하게 StringBuilder를 사용할 수 없습니다.
다음은 내 테스트입니다 (벤치 마크가 아니라 테스트).
public static void main(String[] args) {
String withString ="";
long t0 = System.currentTimeMillis();
for (int i = 0 ; i < 100000; i++){
withString+="some string";
}
System.out.println("strings:" + (System.currentTimeMillis() - t0));
t0 = System.currentTimeMillis();
StringBuffer buf = new StringBuffer();
for (int i = 0 ; i < 100000; i++){
buf.append("some string");
}
System.out.println("Buffers : "+(System.currentTimeMillis() - t0));
t0 = System.currentTimeMillis();
StringBuilder building = new StringBuilder();
for (int i = 0 ; i < 100000; i++){
building.append("some string");
}
System.out.println("Builder : "+(System.currentTimeMillis() - t0));
}
결과 :
문자열 : 319740
버퍼 : 23
작성기 : 7!
따라서 빌더는 버퍼보다 빠르며 문자열 연결보다 빠릅니다. 이제 여러 스레드에 대해 Executor 를 사용합시다 :
public class StringsPerf {
public static void main(String[] args) {
ThreadPoolExecutor executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
//With Buffer
StringBuffer buffer = new StringBuffer();
for (int i = 0 ; i < 10; i++){
executorService.execute(new AppendableRunnable(buffer));
}
shutdownAndAwaitTermination(executorService);
System.out.println(" Thread Buffer : "+ AppendableRunnable.time);
//With Builder
AppendableRunnable.time = 0;
executorService = (ThreadPoolExecutor) Executors.newFixedThreadPool(10);
StringBuilder builder = new StringBuilder();
for (int i = 0 ; i < 10; i++){
executorService.execute(new AppendableRunnable(builder));
}
shutdownAndAwaitTermination(executorService);
System.out.println(" Thread Builder: "+ AppendableRunnable.time);
}
static void shutdownAndAwaitTermination(ExecutorService pool) {
pool.shutdown(); // code reduced from Official Javadoc for Executors
try {
if (!pool.awaitTermination(60, TimeUnit.SECONDS)) {
pool.shutdownNow();
if (!pool.awaitTermination(60, TimeUnit.SECONDS))
System.err.println("Pool did not terminate");
}
} catch (Exception e) {}
}
}
class AppendableRunnable<T extends Appendable> implements Runnable {
static long time = 0;
T appendable;
public AppendableRunnable(T appendable){
this.appendable = appendable;
}
@Override
public void run(){
long t0 = System.currentTimeMillis();
for (int j = 0 ; j < 10000 ; j++){
try {
appendable.append("some string");
} catch (IOException e) {}
}
time+=(System.currentTimeMillis() - t0);
}
}
이제 StringBuffers 걸릴 157 밀리 100000 개 추가하십시오. 동일한 테스트는 아니지만 이전 37ms와 비교하여 멀티 스레딩 사용시 StringBuffers 추가가 더 느리다고 가정 할 수 있습니다 . 그 이유는 JIT / hotspot / compiler / something이 잠금을 확인할 필요 가 없음을 감지하면 최적화하기 때문입니다 .
그러나 StringBuilder를 사용하면 java.lang.ArrayIndexOutOfBoundsException이 발생 합니다. 동시 스레드는 원하지 않는 곳에 무언가를 추가하려고 시도하기 때문입니다.
결론은 StringBuffer를 쫓아 갈 필요가 없다는 것입니다. 그리고 스레드가있는 곳에서 몇 나노 초를 얻기 전에 그들이 무엇을하고 있는지 생각하십시오.
withString+="some string"+i+" ; ";
다른 두 개의 루프에 해당하지 않고, 따라서 공정한 비교가 아닙니다.
StringBuilder는 Java 1.5에서 도입되었으므로 이전 JVM에서는 작동하지 않습니다.
로부터 Javadoc과 :
StringBuilder 클래스는 StringBuffer와 호환되는 API를 제공하지만 동기화를 보장하지는 않습니다. 이 클래스는 문자열 버퍼가 단일 스레드에 의해 사용되는 장소에서 StringBuffer의 드롭 인 대체로 사용하도록 설계되었습니다 (일반적인 경우). 가능한 경우,이 클래스는 대부분의 구현에서 더 빠를 것이기 때문에 StringBuffer에 우선하여 사용하는 것이 좋습니다.
StringBuilder
.
아주 좋은 질문
차이점은 다음과 같습니다.
StringBuffer :-
StringBuffer is synchronized
StringBuffer is thread-safe
StringBuffer is slow (try to write a sample program and execute it, it will take more time than StringBuilder)
StringBuilder :-
StringBuilder is not synchronized
StringBuilder is not thread-safe
StringBuilder performance is better than StringBuffer.
일반적인 것 :-
둘 다 동일한 서명을 가진 동일한 메소드를 가지고 있습니다. 둘 다 변경할 수 있습니다.
StringBuffer
StringBuilder
StringBuffer
다른 변경없이 교체 할 수 있습니다append
두 번이나 append
하고 toString
안전하지 없습니다.
StringBuilder
과 StringBuffer
거의 동일합니다. 차이점은 StringBuffer
동기화되고 동기화 StringBuilder
되지 않는다는 것입니다. 비록 StringBuilder
빨리보다 StringBuffer
, 성능 차이는 거의이다. StringBuilder
의 SUN을 대체 StringBuffer
합니다. 모든 공개 메소드와의 동기화를 피할뿐입니다. 그보다는 기능이 동일합니다.
좋은 사용법의 예 :
텍스트가 변경되어 여러 스레드에서 사용되는 경우을 사용하는 것이 좋습니다 StringBuffer
. 텍스트가 변경되지만 단일 스레드에서 사용되는 경우을 사용하십시오 StringBuilder
.
StringBuffer
StringBuffer는 변경 가능하므로 객체의 값을 변경할 수 있습니다. StringBuffer를 통해 생성 된 객체는 힙에 저장됩니다. StringBuffer는 StringBuilder와 동일한 메소드를 갖지만 StringBuffer의 각 메소드는 동기화되어 StringBuffer는 스레드로부터 안전합니다.
이 때문에 두 개의 스레드가 동일한 메소드에 동시에 액세스 할 수 없습니다. 각 메소드는 한 번에 하나의 스레드로 액세스 할 수 있습니다.
그러나 스레드 안전은 스레드 안전 속성으로 인해 StringBuffer 성능이 저하되므로 단점도 있습니다. 따라서 StringBuilder는 각 클래스의 동일한 메소드를 호출 할 때 StringBuffer보다 빠릅니다.
StringBuffer 값은 변경 될 수 있으며 이는 새로운 값에 할당 될 수 있음을 의미합니다. 요즘 가장 일반적인 면접 질문, 위의 클래스 간의 차이점. toString () 메소드를 사용하여 문자열 버퍼를 문자열로 변환 할 수 있습니다.
StringBuffer demo1 = new StringBuffer(“Hello”) ;
// The above object stored in heap and its value can be changed .
demo1=new StringBuffer(“Bye”);
// Above statement is right as it modifies the value which is allowed in the StringBuffer
StringBuilder
StringBuilder는 StringBuffer와 동일합니다. 즉, 객체를 힙에 저장하고 수정할 수도 있습니다. StringBuffer와 StringBuilder의 주요 차이점은 StringBuilder도 스레드로부터 안전하지 않다는 것입니다. StringBuilder는 스레드 안전하지 않기 때문에 빠릅니다.
StringBuilder demo2= new StringBuilder(“Hello”);
// The above object too is stored in the heap and its value can be modified
demo2=new StringBuilder(“Bye”);
// Above statement is right as it modifies the value which is allowed in the StringBuilder
String
불변입니다.
StringBuffer
변경 가능하고 동기화되었습니다.
StringBuilder
또한 변경 가능하지만 동기화되지 않았습니다.
javadoc에서는 차이를 설명합니다 :
이 클래스는 StringBuffer와 호환되는 API를 제공하지만 동기화를 보장하지는 않습니다. 이 클래스는 문자열 버퍼가 단일 스레드에 의해 사용되는 장소에서 StringBuffer의 드롭 인 대체로 사용하도록 설계되었습니다 (일반적인 경우). 가능한 경우,이 클래스는 대부분의 구현에서 더 빠를 것이기 때문에 StringBuffer에 우선하여 사용하는 것이 좋습니다.
StringBuilder
(Java 5에서 도입)은 StringBuffer
메소드가 동기화되지 않은 것을 제외하고와 합니다. 이는 후자보다 성능이 우수하지만 스레드로부터 안전하지 않다는 단점이 있습니다.
자세한 내용은 튜토리얼 을 읽으십시오 .
StringBuffer와 StringBuilder의 차이점을 보여주는 간단한 프로그램 :
/**
* Run this program a couple of times. We see that the StringBuilder does not
* give us reliable results because its methods are not thread-safe as compared
* to StringBuffer.
*
* For example, the single append in StringBuffer is thread-safe, i.e.
* only one thread can call append() at any time and would finish writing
* back to memory one at a time. In contrast, the append() in the StringBuilder
* class can be called concurrently by many threads, so the final size of the
* StringBuilder is sometimes less than expected.
*
*/
public class StringBufferVSStringBuilder {
public static void main(String[] args) throws InterruptedException {
int n = 10;
//*************************String Builder Test*******************************//
StringBuilder sb = new StringBuilder();
StringBuilderTest[] builderThreads = new StringBuilderTest[n];
for (int i = 0; i < n; i++) {
builderThreads[i] = new StringBuilderTest(sb);
}
for (int i = 0; i < n; i++) {
builderThreads[i].start();
}
for (int i = 0; i < n; i++) {
builderThreads[i].join();
}
System.out.println("StringBuilderTest: Expected result is 1000; got " + sb.length());
//*************************String Buffer Test*******************************//
StringBuffer sb2 = new StringBuffer();
StringBufferTest[] bufferThreads = new StringBufferTest[n];
for (int i = 0; i < n; i++) {
bufferThreads[i] = new StringBufferTest(sb2);
}
for (int i = 0; i < n; i++) {
bufferThreads[i].start();
}
for (int i = 0; i < n; i++) {
bufferThreads[i].join();
}
System.out.println("StringBufferTest: Expected result is 1000; got " + sb2.length());
}
}
// Every run would attempt to append 100 "A"s to the StringBuilder.
class StringBuilderTest extends Thread {
StringBuilder sb;
public StringBuilderTest (StringBuilder sb) {
this.sb = sb;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
sb.append("A");
}
}
}
//Every run would attempt to append 100 "A"s to the StringBuffer.
class StringBufferTest extends Thread {
StringBuffer sb2;
public StringBufferTest (StringBuffer sb2) {
this.sb2 = sb2;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
sb2.append("A");
}
}
}
StringBuffer는 변경 될 문자열을 저장하는 데 사용됩니다 (문자열 개체는 변경할 수 없음). 필요에 따라 자동으로 확장됩니다. 관련 클래스 : String, CharSequence.
StringBuilder는 Java 5에 추가되었습니다. StringBuffer는 동기화되지 않은 것을 제외하고는 StringBuffer와 동일합니다. 즉, 여러 스레드가 동시에 액세스하는 경우 문제가 발생할 수 있습니다. 단일 스레드 프로그램의 경우 동기화 오버 헤드를 피하는 가장 일반적인 경우로 StringBuilder가 약간 더 빠릅니다.
StringBuilder
일반적으로 메소드에 국한되며 하나의 스레드에만 표시됩니다.
StringBuffer 는 변경 가능합니다. 길이와 내용에 따라 변경 될 수 있습니다. StringBuffers는 스레드로부터 안전합니다. 즉, 한 번에 하나의 스레드 만 StringBuffer 객체의 동기화 된 코드에 액세스 할 수 있도록 액세스를 제어하는 동기화 된 메서드가 있습니다. 따라서 StringBuffer 객체는 일반적으로 여러 스레드가 동일한 StringBuffer 객체에 동시에 액세스하려고하는 다중 스레드 환경에서 사용하는 것이 안전합니다.
StringBuilder StringBuilder 클래스는 액세스가 동기화되지 않아 스레드로부터 안전하지 않다는 점을 제외하면 StringBuffer와 매우 유사합니다. 동기화되지 않으면 StringBuilder의 성능이 StringBuffer보다 우수 할 수 있습니다. 따라서 단일 스레드 환경에서 작업하는 경우 StringBuffer 대신 StringBuilder를 사용하면 성능이 향상 될 수 있습니다. 이는 하나의 스레드 만 StringBuilder 객체에 액세스하는 StringBuilder 로컬 변수 (예 : 메서드 내의 변수)와 같은 다른 상황에서도 마찬가지입니다.
StringBuffer :
StringBuilder
String c = a + b
에 해당 String c = new StringBuilder().append(a).append(b).toString()
이 빨리되지 않도록. 그것은 당신이 하나를 가질 수있을 때, 각 문자열 대입을위한 새로운 하나를 만드는 것이 단지입니다 ( String d = a + b; d = d + c;
인 String d = new StringBuilder().append(a).append(b).toString(); d = new StringBuilder().append(d).append(c).toString();
동안 StringBuilder sb = new StringBuilder(); sb.append(a).append(b); sb.append(c); String d = sb.toString();
하나의 StringBuilder instanciation을 절약 할 수).
스트링 빌더 :
int one = 1;
String color = "red";
StringBuilder sb = new StringBuilder();
sb.append("One=").append(one).append(", Color=").append(color).append('\n');
System.out.print(sb);
// Prints "One=1, Colour=red" followed by an ASCII newline.
문자열 버퍼
StringBuffer sBuffer = new StringBuffer("test");
sBuffer.append(" String Buffer");
System.out.println(sBuffer);
StringBuilder는 StringBuffer보다 빠르기 때문에 가능할 때마다 사용하는 것이 좋습니다. 그러나 스레드 안전성이 필요한 경우 최선의 옵션은 StringBuffer 객체입니다.
더 나은 사용 StringBuilder
이되지 않기 때문에 동기화 때문에 더 나은 성능 및 이벤트. 이전 StringBuilder
의 드롭 인 대체 입니다 StringBuffer
.
StringBu(ff|ild)er
단일 스레드에서만 사용되는 로컬 변수입니다.
이후 StringBuffer
동기화되어,이 때문에 perforamance에 따라 약간의 여분의 노력을 필요로 자사는보다 느린 비트 StringBuilder
.
StringBuilder
와 사이에는 기본적인 차이점이 없으며 그 사이 StringBuffer
에는 몇 가지 차이점 만 있습니다. 에서 StringBuffer
방법 동기화됩니다. 이것은 한 번에 하나의 스레드 만 스레드에서 작동 할 수 있음을 의미합니다. 둘 이상의 스레드가있는 경우 두 번째 스레드는 첫 번째 스레드가 완료 될 때까지 기다려야하고 세 번째 스레드는 첫 번째 및 두 번째 스레드가 완료 될 때까지 기다려야합니다. 이로 인해 프로세스가 매우 느려져 성능 StringBuffer
이 저하됩니다.
한편, StringBuilder
동기화되지 않습니다. 이는 한 번에 여러 스레드가 동일한 StringBuilder
객체에서 동시에 작동 할 수 있음을 의미합니다 . 이로 인해 프로세스가 매우 빨라지므로 성능 StringBuilder
이 높습니다.
A는 String
수단 불변 목적 값은 변경 될 수없는 반면StringBuffer
가변이다.
는 StringBuffer
따라서 동기화 스레드 세이프 반면된다 StringBuilder
단지 단일 스레드 인스턴스하지 적합하다.
가장 큰 차이점은 StringBuffer
동기화되어 있지만 그렇지 StringBuilder
않습니다. 둘 이상의 스레드를 사용해야하는 경우 StringBuffer가 권장되지만 동기화 속도 StringBuilder
가 StringBuffer
아니기 때문에 실행 속도 가보다 빠릅니다 .
의 동기화 된 추가 방법 StringBuffer
및 동기화되지 않은 추가 방법의 내부를 확인하십시오 StringBuilder
.
public StringBuffer(String str) {
super(str.length() + 16);
append(str);
}
public synchronized StringBuffer append(Object obj) {
super.append(String.valueOf(obj));
return this;
}
public synchronized StringBuffer append(String str) {
super.append(str);
return this;
}
public StringBuilder(String str) {
super(str.length() + 16);
append(str);
}
public StringBuilder append(Object obj) {
return append(String.valueOf(obj));
}
public StringBuilder append(String str) {
super.append(str);
return this;
}
APPEND이기 때문에 synchronized
, StringBuffer
비교의 성능 오버 헤드를 갖는다 StrinbBuilder
에서 시나리오 멀티 스레딩. 여러 스레드간에 버퍼를 공유하지 StringBuilder
않는 한 synchronized
, append 메소드 가 없기 때문에을 사용하십시오.
다음은 String vs StringBuffer vs StringBuilder 의 성능 테스트 결과입니다 . 마지막으로 StringBuilder가 테스트에서 승리했습니다. 테스트 코드 및 결과는 아래를 참조하십시오.
코드 :
private static void performanceTestStringVsStringbuffereVsStringBuilder() {
// String vs StringBiffer vs StringBuilder performance Test
int loop = 100000;
long start = 0;
// String
String str = null;
start = System.currentTimeMillis();
for (int i = 1; i <= loop; i++) {
str += i + "test";
}
System.out.println("String - " + (System.currentTimeMillis() - start) + " ms");
// String buffer
StringBuffer sbuffer = new StringBuffer();
start = System.currentTimeMillis();
for (int i = 1; i <= loop; i++) {
sbuffer.append(i).append("test");
}
System.out.println("String Buffer - " + (System.currentTimeMillis() - start) + " ms");
// String builder
start = System.currentTimeMillis();
StringBuilder sbuilder = new StringBuilder();
for (int i = 1; i <= loop; i++) {
sbuffer.append(i).append("test");
}
System.out.println("String Builder - " + (System.currentTimeMillis() - start) + " ms");
}
결과 :
단일 텍스트 추가를위한 100000 반복
String - 37489 ms
String Buffer - 5 ms
String Builder - 4 ms
단일 텍스트 추가를위한 10000 회 반복
String - 389 ms
String Buffer - 1 ms
String Builder - 1 ms
StringBuffer는 동기화되어 스레드로부터 안전하며 StringBuilder는 동기화되지 않고 더 빠릅니다.