StringBuffer vs StringBuilder

Supawit R
odds.team
Published in
2 min readJun 9, 2022
String | https://unsplash.com/photos/0ujNS9PMFhM

เคยสงสัยกันไหมครับว่า StringBuffer และ StringBuilder ในภาษา Java ที่ทำหน้าที่เหมือนกันคือ ต่อ String แล้วมันแตกต่างกันยังไง ? จะมาเล่าให้อ่านครับ

TLDR;

StringBuffer คือ StringBuilder เวอร์ชันอัปเกรดให้ทำงานได้ดีบน multi-thread program ในขณะที่ StringBuilder อาจจะเจอปัญหา race condition บน multi-thread แต่หากอยู่บน single thread ถือว่าทำงานได้รวดเร็วกว่า StringBuffer เพราะไม่ต้องจัดการเรื่อง multi-thread

ก่อนเข้าเรื่อง Java มี 3 class ที่ represent data ตัวอักษรที่ต่อเนื่องกัน นั่นคือ String, StringBuffer, StringBuilder

String!!

String เป็น immutable class หมายความว่าเมื่อสร้างมาแล้วเราไม่สามารถแก้ value การที่เราจะต่อ string โดยใช้ class String ตรง ๆ อาจจะไม่ตอบโจทย์เรื่อง performance ครับ เพราะเมื่อก็ตามที่มีการสร้าง String เราก็จะเสีย memory เพื่อเก็บ String ที่เราต้องการมาต่อนั่นเอง กว่าจะมีการคืนให้ memory ก็อาจต้องรอให้ garbage collector มาจัดการ

ดังนั้นแล้ว StringBuffer กับ StringBuilder ก็อาจจะเป็นคำตอบในเรื่องนี้ เพราะ 2 ตัวนี้เป็น data type ที่เป็น mutable ก็ตรงกันข้ามคือเราสามารถแก้ไข value ได้

มาถึงประเด็นของเราแล้วว่า StringBuffer และ StringBuilder ต่างกันยังไง ? หลัก ๆ ความแตกต่างมี 2 เรื่องคือ Efficiency และ Thread Safe

Efficiency

StringBuilder ทำงานได้เร็วกว่า StringBuffer ทดสอบโดยใช้โค้ดด้านล่าง

output

StringBuffer vs StringBuilder time taken output

เหตุผลที่ StringBuffer ช้ากว่า StringBuilder ก็จะเป็นเพราะเรื่องที่ต้องจัดการ Thread-safe

Thread Safe

StringBuffer เป็น thread-safe

StringBuilder ไม่ thread-safe หมายความว่า 2 thread สามารถเรียก method ของ StringBuilder ในเวลาเดียวกันได้

ทำให้ StringBuilder หากนำไปใช้งานแบบ concurrent ต้องใช้อย่างระมัดระวัง เพราะอาจจะเกิดปัญหา visibility problem และได้ผลลัพธ์ที่ไม่ถูกต้องได้

ทดสอบเรื่อง thread-safe ผ่านโค้ดด้านล่าง

output

StringBuffer vs StringBuilder thread safe output

จริง ๆ เราสามารถแก้ปัญหา non-thread safe ของ StringBuilder ให้เป็น thread safe ด้วยการใช้ keyword synchronized แต่ด้าน Efficiency ก็จะน้อยลงไปกลายเป็นเหมือนเราใช้ StringBuffer

StringBuilder sb = new StringBuilder();Runnable r = () -> {    synchronized (sb) {
// do something with 'sb'
}
};

สรุป

การเลือกใช้งานขึ้นอยู่กับโจทย์ว่างานนั้น ๆ เกี่ยวกับเรื่อง concurrent หรือเปล่า ถ้าใช่ StringBuffer ก็น่าจะเป็นคำตอบ ถ้าไม่ใช่ก็ไปใช้ StringBuilder

References

--

--

Supawit R
odds.team

a developer who love to learn, read, and sleep.