java - स्ट्रिंगबिल्डर और स्ट्रिंगबफर के बीच अंतर
stringbuilder stringbuffer (20)
StringBuffer
और StringBuilder
बीच मुख्य अंतर क्या है? इनमें से किसी एक पर निर्णय लेने पर कोई प्रदर्शन समस्या है?
बहुत अच्छा सवाल है
यहां अंतर हैं, मैंने देखा है:
स्ट्रिंगबफर: -
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.
आम बात :-
दोनों के समान हस्ताक्षर के साथ एक ही तरीके हैं। दोनों उत्परिवर्तनीय हैं।
लेकिन एक उदाहरण की मदद से स्पष्ट अंतर पाने की जरूरत है?
स्ट्रिंगबफर या स्ट्रिंगबिल्डर
बस StringBuilder
उपयोग करें जबतक कि आप वास्तव में धागे के बीच बफर साझा करने का प्रयास नहीं कर रहे हैं। StringBuilder
मूल सिंक्रनाइज़ StringBuffer
वर्ग के छोटे भाई को बिना सिंक्रनाइज़ (कम ओवरहेड = अधिक कुशल) है।
StringBuffer
पहले आया था। सूर्य सभी स्थितियों के तहत शुद्धता से चिंतित था, इसलिए उन्होंने इसे मामले में थ्रेड-सुरक्षित बनाने के लिए सिंक्रनाइज़ किया।
StringBuilder
बाद में आया। StringBuffer
अधिकांश उपयोग सिंगल-थ्रेड थे और अनावश्यक रूप से सिंक्रनाइज़ेशन की लागत का भुगतान करते थे।
चूंकि StringBuilder
सिंक्रनाइज़ेशन के बिना StringBuffer
लिए एक ड्रॉप-इन प्रतिस्थापन है , इसलिए किसी भी उदाहरण के बीच अंतर नहीं होगा।
यदि आप थ्रेड के बीच साझा करने का प्रयास कर रहे हैं , तो आप StringBuffer
उपयोग कर सकते हैं, लेकिन इस बात पर विचार करें कि उच्च स्तरीय सिंक्रनाइज़ेशन आवश्यक है, उदाहरण के लिए शायद स्ट्रिंगबफर का उपयोग करने के बजाय, क्या आपको स्ट्रिंगबिल्डर का उपयोग करने वाली विधियों को सिंक्रनाइज़ करना चाहिए।
एकल धागे में, स्ट्रिंगबफरर स्ट्रिंगबिल्डर से काफी धीमी नहीं है , जेवीएम अनुकूलन के लिए धन्यवाद। और मल्टीथ्रेडिंग में, आप सुरक्षित रूप से स्ट्रिंगबिल्डर का उपयोग नहीं कर सकते हैं।
मेरा परीक्षण यहाँ है:
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));
}
परिणाम:
तार: 31 9 740
बफर: 23
बिल्डर: 7!
तो बिल्डर्स बफर की तुलना में तेज़ हैं, और स्ट्रिंग्स कॉन्सटेनेशन से तेज़ तरीके से हैं। अब चलिए एक थ्रेड के लिए एक निष्पादक का उपयोग करते हैं:
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);
}
}
अब स्ट्रिंगबफर 100000 एपेंड के लिए 157 एमएस लेते हैं। यह एक ही परीक्षण नहीं है, लेकिन पिछले 37 एमएस की तुलना में, आप सुरक्षित रूप से मान सकते हैं कि स्ट्रिंगबफर्स संलग्न मल्टीथ्रेडिंग उपयोग के साथ धीमे हैं । इसका कारण यह है कि जेआईटी / हॉटस्पॉट / कंपाइलर / कुछ अनुकूलन करता है जब यह पता लगाता है कि ताले की जांच करने की कोई आवश्यकता नहीं है।
लेकिन स्ट्रिंगबिल्डर के साथ, आपके पास java.lang.ArrayIndexOutOfBoundsException है , क्योंकि एक समवर्ती थ्रेड कुछ ऐसा जोड़ने की कोशिश करता है जहां इसे नहीं करना चाहिए।
निष्कर्ष यह है कि आपको स्ट्रिंगबफर का पीछा करने की आवश्यकता नहीं है। और जहां आपके पास धागे हैं, कुछ नैनोसेकंड प्राप्त करने की कोशिश करने से पहले, वे क्या कर रहे हैं, इसके बारे में सोचें।
चूंकि StringBuffer
सिंक्रनाइज़ किया गया है, इसलिए इसे कुछ अतिरिक्त प्रयासों की आवश्यकता है, इसलिए छिद्रण के आधार पर, यह स्ट्रिंगबिल्डर से थोड़ा धीमा है।
यह लिंक आपको String
और String
की अवधारणाओं को समझ नहीं पाएगा बल्कि String
क्लास के साथ उनके सहयोग और अंतर भी बनाएगा। यह आपको समझ जाएगा कि किस वर्ग का उपयोग करना है। http://www.acquireandinspire.org/2013/01/string-string-builder-string-buffer.html
सबसे पहले समानताएं देखें: स्ट्रिंगबिल्डर और स्ट्रिंगबफर दोनों उत्परिवर्तनीय हैं। इसका मतलब है कि आप उसी स्थान पर, उनकी सामग्री को बदल सकते हैं।
मतभेद : स्ट्रिंगबफर म्यूटेबल और सिंक्रनाइज़ भी है। जहां स्ट्रिंगबिल्डर म्यूटेबल है लेकिन डिफ़ॉल्ट रूप से सिंक्रनाइज़ नहीं होता है।
सिंक्रनाइज़ (सिंक्रनाइज़ेशन) का अर्थ : जब कुछ चीज सिंक्रनाइज़ होती है, तो एकाधिक थ्रेड एक्सेस कर सकते हैं, और इसे किसी भी समस्या या साइड इफेक्ट के साथ संशोधित कर सकते हैं। स्ट्रिंगबफर सिंक्रनाइज़ किया गया है, इसलिए आप इसे किसी भी समस्या के साथ कई धागे के साथ उपयोग कर सकते हैं।
किसका उपयोग करने के लिए? स्ट्रिंगबिल्डर: जब आपको एक स्ट्रिंग की आवश्यकता होती है, जिसे संशोधित किया जा सकता है, और केवल एक थ्रेड इसे एक्सेस कर रहा है और इसे संशोधित कर रहा है। स्ट्रिंगबफर: जब आपको एक स्ट्रिंग की आवश्यकता होती है, जिसे संशोधित किया जा सकता है, और एकाधिक थ्रेड इसे एक्सेस कर रहे हैं और इसे संशोधित कर रहे हैं।
नोट : स्ट्रिंगबफर को अनावश्यक रूप से उपयोग न करें, यानी, इसका उपयोग न करें अगर केवल एक थ्रेड संशोधित हो रहा है और इसे एक्सेस कर रहा है क्योंकि इसमें सिंक्रनाइज़ेशन के लिए लॉकिंग और अनलॉकिंग कोड है जो अनावश्यक रूप से CPU समय ले लेगा। जब तक यह आवश्यक न हो तो ताले का उपयोग न करें।
स्ट्रिंगबफर और स्ट्रिंगबिल्डर के बीच अंतर को चित्रित करने वाला एक सरल कार्यक्रम:
/**
* 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");
}
}
}
स्ट्रिंगबफर का उपयोग चरित्र तारों को संग्रहीत करने के लिए किया जाता है जो बदले जाएंगे (स्ट्रिंग ऑब्जेक्ट्स को बदला नहीं जा सकता है)। यह स्वचालित रूप से आवश्यकतानुसार फैलता है। संबंधित वर्ग: स्ट्रिंग, CharSequence।
स्ट्रिंगबिल्डर को जावा 5 में जोड़ा गया था। यह स्ट्रिंगबफर के सभी मामलों में समान है, सिवाय इसके कि यह सिंक्रनाइज़ नहीं है, जिसका अर्थ यह है कि यदि एक ही समय में एकाधिक थ्रेड इसे एक्सेस कर रहे हैं, तो समस्या हो सकती है। सिंगल थ्रेडेड प्रोग्राम्स के लिए, सिंक्रनाइज़ेशन के ओवरहेड से परहेज करने वाला सबसे आम मामला स्ट्रिंगबिल्डर को थोड़ा तेज़ बनाता है।
स्ट्रिंगबिल्डर का बेहतर उपयोग करें क्योंकि यह सिंक्रनाइज़ नहीं है और बेहतर प्रदर्शन के लिए है। स्ट्रिंगबिल्डर पुराने स्ट्रिंगबफर का ड्रॉप-इन प्रतिस्थापन है।
स्ट्रिंगबिल्डर को जावा 1.5 में पेश किया गया था, इसलिए यह पहले के जेवीएम के साथ काम नहीं करेगा।
स्ट्रिंगबिल्डर वर्ग स्ट्रिंगबफर के साथ एक एपीआई संगत प्रदान करता है, लेकिन सिंक्रनाइज़ेशन की कोई गारंटी नहीं है। इस वर्ग को उन स्थानों पर स्ट्रिंगबफर के लिए ड्रॉप-इन प्रतिस्थापन के रूप में उपयोग के लिए डिज़ाइन किया गया है जहां स्ट्रिंग बफर का उपयोग एक थ्रेड द्वारा किया जा रहा था (जैसा आम तौर पर मामला है)। जहां संभव हो, यह अनुशंसा की जाती है कि इस वर्ग का उपयोग स्ट्रिंगबफर को प्राथमिकता में किया जाए क्योंकि यह अधिकतर कार्यान्वयन के तहत तेज़ी से होगा।
स्ट्रिंगबिल्डर स्ट्रिंगबफर से बहुत तेज है क्योंकि यह गैर सिंक्रनाइज़ नहीं है।
यहां आपको सिंक्रनाइज़ करने की लागत के बारे में अधिक जानकारी मिली है
प्रोग्रामिंग रूप से देखें कि स्ट्रिंगबिल्डर स्ट्रिंगबफर से कितना तेज़ है
public class Test{
public static void main(String[] args){
long startTime = System.currentTimeMillis();
StringBuffer sb = new StringBuffer("Yasir");
for (int i=0; i<10000; i++){
sb.append("Shabbir");
}
System.out.println("Time taken by StringBuffer: " + (System.currentTimeMillis() - startTime) + "ms");
startTime = System.currentTimeMillis();
StringBuilder sb2 = new StringBuilder("Yasir");
for (int i=0; i<10000; i++){
sb2.append("Shabbir");
}
System.out.println("Time taken by StringBuilder: " + (System.currentTimeMillis() - startTime) + "ms");
}
}
उत्पादन
स्ट्रिंगबफर द्वारा लिया गया समय: 16 एमएमएस
स्ट्रिंगबिल्डर द्वारा लिया गया समय: 0 एमएमएस
StringBuffer
सिंक्रनाइज़ किया गया है, StringBuilder
नहीं है।
javadoc अंतर बताता है:
यह वर्ग स्ट्रिंगबफर के साथ एक एपीआई संगत प्रदान करता है, लेकिन सिंक्रनाइज़ेशन की कोई गारंटी नहीं है। इस वर्ग को उन स्थानों पर स्ट्रिंगबफर के लिए ड्रॉप-इन प्रतिस्थापन के रूप में उपयोग के लिए डिज़ाइन किया गया है जहां स्ट्रिंग बफर का उपयोग एक थ्रेड द्वारा किया जा रहा था (जैसा आम तौर पर मामला है)। जहां संभव हो, यह अनुशंसा की जाती है कि इस वर्ग का उपयोग स्ट्रिंगबफर को प्राथमिकता में किया जाए क्योंकि यह अधिकतर कार्यान्वयन के तहत तेज़ी से होगा।
String
एक अपरिवर्तनीय है।
StringBuffer
एक उत्परिवर्तनीय और सिंक्रनाइज़ है।
StringBuilder
भी उत्परिवर्तनीय है लेकिन यह सिंक्रनाइज़ नहीं है।
StringBuffer
के सिंक्रनाइज़ेड एपेंड विधि के आंतरिक और StringBuffer
गैर-सिंक्रनाइज़ेड एपेंड विधि की जांच करें।
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;
}
चूंकि परिशिष्ट synchronized
, StrinbBuilder
के पास बहु-थ्रेडिंग परिदृश्य में StrinbBuilder
की तुलना में प्रदर्शन ओवरहेड है। जब तक आप एकाधिक धागे के बीच बफर साझा नहीं कर रहे हैं, तब तक StringBuilder
उपयोग करें, जो कि संलग्न तरीकों में synchronized
अनुपस्थिति के कारण तेज़ है।
StringBuffer
सिंक्रनाइज़ किया गया है, लेकिन StringBuilder
नहीं है। नतीजतन, StringBuilder
से तेज है।
StringBuilder
और StringBuffer
लगभग समान हैं। अंतर यह है कि StringBuffer
सिंक्रनाइज़ किया गया है और StringBuilder
नहीं है। हालांकि, StringBuilder
से तेज है, प्रदर्शन में अंतर बहुत कम है। StringBuilder
का एक सूर्य का प्रतिस्थापन है। यह सिर्फ सभी सार्वजनिक तरीकों से सिंक्रनाइज़ेशन से बचाता है। इसके बजाय, उनकी कार्यक्षमता वही है।
अच्छे उपयोग का उदाहरण:
यदि आपका टेक्स्ट बदलने जा रहा है और एकाधिक धागे द्वारा उपयोग किया जाता है, तो StringBuffer
का उपयोग करना बेहतर होता है। यदि आपका टेक्स्ट बदलने जा रहा है लेकिन एक थ्रेड द्वारा उपयोग किया जाता है, तो StringBuilder
उपयोग करें।
StringBuffer:
- अनेक परतदार
- सिंक्रनाइज़
- स्ट्रिंगबिल्डर से धीमा
StringBuilder
- एकल थ्रेड
- नहीं-सिंक्रनाइज़
- स्ट्रिंग से पहले तेज
StringBuffer
स्ट्रिंगबफर उत्परिवर्तनीय है इसका मतलब है कि कोई वस्तु के मान को बदल सकता है। स्ट्रिंगबफर के माध्यम से बनाई गई वस्तु ढेर में संग्रहीत होती है। स्ट्रिंगबफर के पास स्ट्रिंगबिल्डर के समान तरीके हैं, लेकिन स्ट्रिंगबफर में प्रत्येक विधि सिंक्रनाइज़ होती है जो स्ट्रिंगबफर थ्रेड सुरक्षित है।
StringBuilder
स्ट्रिंगबिल्डर स्ट्रिंगबफर के समान है, यह वस्तु को ढेर में संग्रहीत करता है और इसे भी संशोधित किया जा सकता है। स्ट्रिंगबफर और स्ट्रिंगबिल्डर के बीच मुख्य अंतर यह है कि स्ट्रिंगबिल्डर थ्रेड सुरक्षित नहीं है। स्ट्रिंगबिल्डर तेज है क्योंकि यह थ्रेड सुरक्षित नहीं है।
स्ट्रिंग-बिल्डर :
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);
जब भी संभव हो तो स्ट्रिंगबिल्डर का उपयोग करने की अनुशंसा की जाती है क्योंकि यह स्ट्रिंगबफर से तेज है। हालांकि, अगर थ्रेड सुरक्षा आवश्यक है, तो सबसे अच्छा विकल्प स्ट्रिंगबफर ऑब्जेक्ट्स है।