Kiedy powinienem używać StringBuilder lub StringBuffer?


13

W produkcyjnej aplikacji internetowej moi koledzy programiści używali StringBuffer wszędzie. Teraz zajmuję się tworzeniem aplikacji i poprawkami. Po przeczytaniu StringBuilder i StringBuffer postanowiłem zastąpić cały kod StringBuffer StringBuilder, ponieważ nie potrzebujemy bezpieczeństwa wątków w naszych komponentach bean danych.

Na przykład: (W każdej fasoli danych widzę użycie 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);
}

Tworzymy osobne komponenty danych dla każdej sesji / żądania. Sesja jest używana przez jednego użytkownika, do którego żaden inny użytkownik nie może uzyskać dostępu.

Czy powinienem rozważyć inne punkty przed migracją?

Jeśli istnieje jeden wątek (brak oczekujących wątków / żaden nowy wątek nie będzie szukał blokady obiektu), działa on równo z StringBuffer lub StringBuilder. Wiem, że w przypadku StringBuffer zabranie blokady obiektu wymaga czasu, ale chcę wiedzieć, czy istnieje jakakolwiek różnica w wydajności między nimi, z wyjątkiem wstrzymania / zwolnienia blokady obiektu.


9
Jeśli użyjesz sbjako zmiennej lokalnej, jak w twoim przykładzie, bezpieczeństwo wątków w ogóle nie ma znaczenia. Nawet gdyby tysiąc wątków jednocześnie wprowadziło metodę, każdy miałby swój własny stos wywołań z własnymi zmiennymi lokalnymi. StringBuilders nigdy nie będą sobie przeszkadzać.
— fredoverflow

Zawsze zastanawiałem się, kto chce zsynchronizować dwa wątki wzdłuż czegoś takiego jak interfejs StringBuffer. Nigdy nie widziałem takiego kodu, ale jestem prawie pewien, że jest to zły projekt z perspektywy wielowątkowości. Ponieważ myślę, że synchronizacja wątku wzdłuż StringBufferinterfejsu jest złym pomysłem, myślę, że ta klasa nie powinna istnieć i zawsze należy jej używać StringBuilder. Jak już wspomniano inni, StringBufferistnieje z powodów historycznych.
— pasztorpisti

Odpowiedzi:


22

Jedyną różnicą między nimi jest synchronizacja używana w StringBuffer. Narzut związany z synchronizacją nie jest ogromny w wielkim schemacie rzeczy, ale jest znaczący w stosunku do metod StringBuilder, które ich nie mają. JVM wykonuje pracę, której inaczej nie musiałby wykonywać - szczególnie z jednym wątkiem itp.

Jeśli Twój kod działa, a ludzie nie narzekają na wydajność, nie martwię się o to. Nie zarobisz dużo za swoje pieniądze. Jeśli jednak piszesz nowy kod lub aktualizujesz kod, który używa StringBuffer, sugerowałbym ich konwersję StringBuilder w tym samym czasie.


Dodam do tego, że należy pamiętać o odziedziczonym bezpieczeństwie wątku tych dwóch. StringBuilder nie jest bezpieczny dla wątków.
— Martijn Verburg

2
@MartijnVerburg Prawda, chociaż zostało to wskazane w stackoverflow.com/questions/6775016/stringbuffer-is-obsolete/…, że istnieje bardzo niewiele przypadków użycia wymagających wielu wątków, aby użyć tego samego wystąpienia Konstruktora ciągów.
— Matthew Flynn

4
@MartijnVerburg: należy również zauważyć: jeśli jesteś naprawdę potrzebują bezpieczeństwa wątku to są szanse, że StringBuffernie jest wystarczająca albo! Gwarantuje, że nie hamuje, ale pozycji, w której dołączasz, nie można łatwo kontrolować, jeśli dostęp do niej ma wiele wątków jednocześnie, więc potrzebna byłaby kolejna synchronizacja zewnętrzna.
— Joachim Sauer

8

StringBuilder został dodany w pewnym momencie (Java 1.5), aby być lepszym i szybszym StringBuffer, a kompilator używa go pod maską do implementacji +operatora na Strings.

Oznacza to, że przy użyciu StringBuilder nie można sprawić, aby kod działał na JVM starszych niż w momencie wprowadzenia klasy. Przez pewien czas byłby to dla nas problem. Jeśli zawsze korzystasz z najnowszej wersji, nie musisz się tym przejmować.

Nie przechodziłbym przez proces optymalizacji, który przechodzisz, choć z następujących powodów.

  • Poza ciasnymi pętlami przewaga jest znikoma. O ile nie pojawi się wyraźnie jako punkt dostępu w profilerze, nie zawracałbym sobie głowy.
  • Zmiana kodu może powodować błędy i musisz dokładnie przetestować aplikację. Może to być znacznie droższe niż życie z klasą zsynchronizowaną w niezsynchronizowanym otoczeniu.

Zgadzam się z tobą .. nadal nie rozumiem twojego sensuOutside tight loops the advantage is negligible...
— Satish Pandey

Mechanizmem, którego brakuje w StringBuilder w przeciwieństwie do StringBuffer, jest szybkość handlu dla bezpieczeństwa wątków. Ta poprawa prędkości jest bardzo mała, więc ma to znaczenie tylko wtedy, gdy jest wykonywana wiele razy - zwykle dzieje się tak w przypadku małej pętli wykonywanej wiele razy.
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.