Heim  >  Artikel  >  Java  >  So verwenden Sie den StringBuilder von Java in Hochleistungsszenarien richtig

So verwenden Sie den StringBuilder von Java in Hochleistungsszenarien richtig

WBOY
WBOYnach vorne
2023-05-12 13:07:06650Durchsuche

Korrekte Verwendung von StringBuilder in Hochleistungsszenarien

Über StringBuilder denken die meisten Schüler einfach daran, dass Sie StringBuilder zum String-Spleißen verwenden sollten, nicht + verwenden und StringBuffer nicht verwenden sollten, dann ist die Leistung am besten, stimmt das? ? Wirklich?

Einige Schüler haben auch drei besondere Erfahrungen gehört:

1. Nach der Java-Kompilierung und -Optimierung ist StringBuilder nicht threadsicher und es ist besser, es zu verwenden von „security“ StringBuffer;

3. Spleißen Sie die Zeichenfolge der Protokollinformationen niemals selbst, sondern überlassen Sie es slf4j.

1. Die anfängliche Länge ist so wichtig, dass sie es verdient, viermal erwähnt zu werden.

StringBuilder enthält ein char[], und konstantes append() ist der Prozess des ständigen Ausfüllens von char[].

Die Standardlänge von char[] bei Verwendung von new StringBuilder() beträgt 16. Was soll ich dann tun, wenn ich das 17. Zeichen anhängen möchte?

Verwenden Sie System.arraycopy, um das Kopieren zu verdoppeln und die Kapazität zu erweitern! ! ! !

Auf diese Weise fallen Kosten für das Kopieren des Arrays an, und zweitens wird auch das ursprüngliche Zeichen [] verschwendet und geht durch GC verloren. Wie Sie sich vorstellen können, wurde eine Zeichenfolge mit 129 Zeichen viermal kopiert und verworfen, 16, 32, 64 und 128, und insgesamt wurden dem Array 496 Zeichen zugewiesen. In einem Hochleistungsszenario ist dies fast der Fall unerträglich.

Wie wichtig ist es also, einen vernünftigen Anfangswert festzulegen.

Aber was ist, wenn ich wirklich nicht gut schätze? Solange die Saite am Ende größer als 16 ist, ist es besser, die Kapazität zu verdoppeln, auch wenn sie etwas verschwendet ist.

2. Die StringBundler-Klasse von Liferay bietet eine weitere Idee der Längeneinstellung. Beim Anhängen () werden die Dinge nicht in Eile in char[] gestopft, sondern zunächst ein String[]. Speichern Sie sie alle Addieren Sie am Ende die Längen aller Strings, um einen StringBuilder mit angemessener Länge zu erstellen.

3. Allerdings wird das Doppelte des Zeichens[] immer noch verschwendet

Die Verschwendung erfolgt im letzten Schritt, StringBuilder.toString()

// Erstellen Sie eine Kopie, geben Sie das Array nicht frei

return new String(value , 0, count); Der Konstruktor von

String verwendet System.arraycopy(), um das eingehende Zeichen[] zu kopieren, um Sicherheit und Unveränderlichkeit zu gewährleisten. Wenn die Geschichte so endet, wird das Zeichen[] in StringBuilder immer noch verschwendet . geopfert.

Um diese char[] nicht zu verschwenden, besteht eine Möglichkeit darin, verschiedene schwarze Technologien wie Unsafe zu verwenden, um den Konstruktor zu umgehen und dem char[]-Attribut von String direkt einen Wert zuzuweisen, aber nur wenige Leute tun dies.

Eine weitere zuverlässigere Methode ist die Wiederverwendung von StringBuilder. Die Wiederverwendung löst auch das vorherige Problem der Längeneinstellung, denn selbst wenn die Schätzung zu Beginn nicht genau ist, reicht sie nach einigen weiteren Erweiterungen aus.

4. StringBuilder wiederverwenden

Diese Methode stammt aus der BigDecimal-Klasse im JDK (es ist in Ordnung, zu sehen, wie wichtig der JDK-Code ist, der den Code in StringBuilderHolder extrahiert, der nur eine Funktion hat: public StringBuilder getStringBuilder(). ) {

sb .setLength(0);

return sb;

}

Die Funktion StringBuilder.setLength() setzt nur ihren Zählzeiger zurück, während char[] weiterhin wiederverwendet wird und toString() auch den aktuellen zurücksetzt count-Zeiger. Übergeben Sie ihn als Parameter an den String-Konstruktor, sodass Sie sich keine Sorgen machen müssen, dass alte Inhalte übergeben werden, die die Größe des neuen Inhalts überschreiten. Es ist ersichtlich, dass StringBuilder vollständig wiederverwendbar ist.


Um Parallelitätskonflikte zu vermeiden, wird dieser Halter im Allgemeinen auf ThreadLocal gesetzt. Informationen zu Standardschreibmethoden finden Sie in den Kommentaren von BigDecimal oder StringBuilderHolder.

5. + und StringBuilder

String s = „hello“ + user.getName();

Die Wirkung dieses Satzes nach der Javac-Kompilierung entspricht tatsächlich der Verwendung von StringBuilder, die Länge ist jedoch nicht festgelegt.

String s = new StringBuilder().append(“hello”).append(user.getName());

Aber wenn es so ist:

String s = “hello”;

// Nach einigen anderen Anweisungen

s = s + user.getName();

Jede Anweisung generiert einen neuen StringBuilder. Hier gibt es zwei StringBuilder, und die Leistung ist völlig unterschiedlich. Wenn s+=i; im Schleifenkörper steht, wird es noch lächerlicher.

Laut R University werden die fleißigen JVM-Ingenieure hart daran arbeiten, benachbarte (ohne Steueranweisungen) StringBuilder gemäß +XX:+OptimizeStringConcat (standardmäßig nach JDK7u40 geöffnet) während der Laufoptimierungsphase zu kombinieren .

Verwenden Sie also sicherheitshalber weiterhin StringBuilder und legen Sie die Länge selbst fest.

6. StringBuffer und StringBuilder

StringBuffer und StringBuilder erben beide von AbstractStringBuilder. Der einzige Unterschied besteht darin, dass StringBuffer-Funktionen das synchronisierte Schlüsselwort haben.

Für diejenigen Studenten, die sagen, dass StringBuffer „sicher“ ist: Wann haben Sie tatsächlich gesehen, dass mehrere Threads abwechselnd einen StringBuffer anhängen? ? ?

7. Überlassen Sie das Spleißen der Protokollzeichenfolge immer slf4j??

logger.info("Hello {}", user.getName());

Überlassen Sie es bei Protokollen, von denen Sie nicht wissen, ob sie ausgegeben werden sollen Durch die Verknüpfung mit slf4j können in der Tat Kosten gespart werden, indem die Ausgabe nur dann gespleißt wird, wenn sie wirklich benötigt wird.

Aber für Protokolle, die ausgegeben werden müssen, ist es schneller, StringBuilder zu verwenden, um sie selbst zu verbinden. Denn wenn man sich die Implementierung von slf4j ansieht, handelt es sich tatsächlich nur um einen konstanten indexof("{}"), einen konstanten subString() und die ständige Verwendung von StringBuilder zum Zusammensetzen. Es gibt kein Allheilmittel.

PS. Der StringBuilder in slf4j reserviert 50 Zeichen außerhalb der ursprünglichen Nachricht. Wenn sich die Variablenparameter auf mehr als 50 Zeichen summieren, müssen sie trotzdem kopiert und erweitert werden ... und der StringBuilder wird nicht wiederverwendet.

Das obige ist der detaillierte Inhalt vonSo verwenden Sie den StringBuilder von Java in Hochleistungsszenarien richtig. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen