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.

Satish Pandey
źródło
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.

Matthew Flynn
źródło
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.
Frank Shearar
źródło
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.