Khi nào tôi nên sử dụng StringBuilder hoặc StringBuffer?


13

Trong một ứng dụng web sản xuất, các lập trình viên đồng nghiệp của tôi đã sử dụng StringBuffer ở mọi nơi. Bây giờ tôi đang chăm sóc phát triển ứng dụng và sửa chữa. Sau khi đọc StringBuilderStringBuffer, tôi đã quyết định thay thế tất cả mã StringBuffer bằng StringBuilder vì chúng tôi không cần sự an toàn của luồng trong các bean dữ liệu của chúng tôi.

Ví dụ: (Trong mỗi bean dữ liệu tôi có thể thấy việc sử dụng StringBuffer)

@Override
public String toString() {
    StringBuffer sb = new StringBuffer();// replace it from StringBuilder
    sb.append(" ABCD : ").append(abcd);
    sb.append(", EFGH : ").append(efgh);
    sb.append(", IJKL : ").append(ijkl);
}

Chúng tôi tạo một bean dữ liệu riêng cho mỗi phiên / yêu cầu. Một phiên được sử dụng bởi một người dùng mà không người dùng nào khác có thể truy cập.

Tôi có nên xem xét các điểm khác trước khi di chuyển?

Nếu có một luồng đơn (không có luồng chờ / không có luồng mới nào sẽ tìm khóa đối tượng), thì nó sẽ hoạt động như nhau với StringBuffer hoặc StringBuilder. Tôi biết trong trường hợp của StringBuffer, cần có thời gian để khóa đối tượng nhưng tôi muốn biết liệu có bất kỳ sự khác biệt nào về hiệu năng giữa chúng ngoại trừ việc giữ / nhả khóa đối tượng hay không.


9
Nếu bạn sử dụng sbnhư một biến cục bộ như trong ví dụ của bạn, thì an toàn luồng không thành vấn đề. Ngay cả khi một ngàn luồng đồng thời nhập vào phương thức, mỗi luồng sẽ có ngăn xếp cuộc gọi riêng với các biến cục bộ của riêng nó. StringBuilders sẽ không bao giờ can thiệp lẫn nhau.
dòng chảy

Tôi luôn tự hỏi ai muốn đồng bộ hóa hai luồng dọc theo thứ gì đó giống như giao diện của a StringBuffer. Tôi chưa bao giờ thấy mã như vậy nhưng tôi gần như chắc chắn đó là một thiết kế tồi từ góc độ đa luồng. Vì tôi nghĩ rằng việc đồng bộ hóa luồng dọc theo StringBuffergiao diện là một ý tưởng tồi, tôi nghĩ rằng lớp này không nên tồn tại và người ta phải luôn luôn sử dụng StringBuilder. Như những người khác đã đề cập, StringBuffertồn tại vì lý do lịch sử.
pasztorpisti

Câu trả lời:


22

Sự khác biệt duy nhất giữa hai là đồng bộ hóa được sử dụng trong StringBuffer. Chi phí đồng bộ hóa không lớn trong sơ đồ lớn của mọi thứ, nhưng nó có ý nghĩa liên quan đến các phương thức StringBuilder không có chúng. JVM đang làm việc mà nó sẽ không phải làm - đặc biệt là chỉ với một luồng, v.v.

Nếu mã của bạn hoạt động và mọi người không phàn nàn về hiệu suất, tôi sẽ không lo lắng về nó. Bạn sẽ không nhận được nhiều tiếng nổ cho đồng tiền của mình. Tuy nhiên, nếu bạn đang viết mã mới hoặc đang cập nhật mã sử dụng StringBuffer, tôi khuyên bạn nên chuyển đổi StringBuilder cùng một lúc.


Tôi sẽ nói thêm rằng bạn cần lưu ý đến sự an toàn của chủ đề kế thừa của cả hai. StringBuilder không phải là chủ đề an toàn.
Martijn Verburg

2
@MartijnVerburg Đúng, altough nó đã được chỉ ra trong stackoverflow.com/questions/6775016/stringbuffer-is-obsolete/... rằng có rất ít trường hợp sử dụng đòi hỏi phải có nhiều chủ đề để sử dụng cùng một ví dụ của một người thợ xây String.
Matthew Flynn

4
@MartijnVerburg: cũng cần lưu ý: nếu bạn thực sự cần sự an toàn của luồng thì rất có thể điều đó StringBuffercũng không đủ! Nó đảm bảo rằng nó không phanh, nhưng vị trí mà bạn nối thêm không thể dễ dàng được kiểm soát nếu nhiều luồng truy cập cùng một lúc, do đó sẽ cần một sự đồng bộ hóa bên ngoài khác.
Joachim Sauer

8

StringBuilder đã được thêm vào tại một điểm (Java 1.5) để trở thành StringBuffer tốt hơn và nhanh hơn và trình biên dịch sử dụng nó dưới mui xe để triển +khai toán tử trên Chuỗi.

Điều này có nghĩa là bằng cách sử dụng StringBuilder, bạn không thể làm cho mã của mình chạy trên JVM cũ hơn khi lớp được giới thiệu. Điều này sẽ là một vấn đề với chúng tôi, trong một thời gian. Nếu bạn luôn chạy mới nhất, bạn không cần phải quan tâm.

Tôi sẽ không trải qua quá trình tối ưu hóa mà bạn trải qua, mặc dù vì những lý do sau.

  • Bên ngoài vòng lặp chặt chẽ lợi thế là không đáng kể. Trừ khi nó hiển thị rõ ràng như một điểm nóng trong một hồ sơ, tôi sẽ không bận tâm.
  • Thay đổi mã có thể gây ra lỗi và bạn phải kiểm tra lại ứng dụng của mình một cách kỹ lưỡng. Điều đó có thể tốn kém hơn rất nhiều so với việc sống với một lớp được đồng bộ hóa trong một môi trường không đồng bộ.

Tôi đồng ý với bạn .. vẫn không thể hiểu quan điểm của bạnOutside tight loops the advantage is negligible...
Satish Pandey

Cơ chế bị thiếu trong StringBuilder trái ngược với StringBuffer là tốc độ giao dịch để bảo mật luồng. Sự cải thiện tốc độ đó là rất nhỏ, vì vậy nó chỉ quan trọng nếu nó được thực hiện rất nhiều lần - đây thường là trường hợp trong một vòng lặp nhỏ được thực hiện nhiều lần.
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.