Vorwort
Dies ist in dieser Zeit ziemlich untätig, also habe ich mir den JDK -Quellcode angesehen. Ein allgemeiner leitender Entwicklungsingenieur kann sich verbessern, indem er einen Quellcode liest. Dieser Artikel fasst einige "kleine Tipps" im JDK -Quellcode zusammen und teilt sie für Ihre Referenz und Lernen. Ich werde unten nicht viel sagen, schauen wir uns die detaillierte Einführung zusammen an.
1 i ++ vs i-
Zeile 985 des String -Quellcodes in Equals -Methode
while (n-! = 0) {if (v1 [i]! = v2 [i]) return false; i ++; }Dieser Code wird verwendet, um zu beurteilen, ob die Zeichenfolge gleich ist, aber es gibt eine seltsame Sache, die i-! = 0 verwendet, um Urteile zu fällen. Verwenden wir normalerweise nicht i ++? Warum verwenden ich ich-? Und die Anzahl der Zyklen ist gleich. Der Grund dafür ist, dass es nach der Zusammenstellung eine weitere Anweisung geben wird:
I- Der Vorgang selbst wirkt sich auf CPSR aus (aktuelles Programmstatusregister). Häufige Flags für CPSR sind N (Ergebnis ist negativ), Z (Ergebnis ist 0), C (Trage) und O (Überlauf). i> 0, kann direkt nach der Z -Flagge beurteilt werden.
Der Betrieb von I ++ wirkt sich auch auf das CPSR (aktuelles Programmstatusregister) aus, beeinflusst jedoch nur das O -Flag (mit Überlauf), was bei der Beurteilung von i <n nicht hilft. Daher ist eine zusätzliche Vergleichsanweisung erforderlich, was bedeutet, dass eine weitere Anweisung für jede Schleife ausgeführt werden muss.
Einfach ausgedrückt, im Vergleich zu 0 wird es eine Anweisung weniger geben. Daher recyceln Sie i-, High-End, Atmosphärische und High-End.
2 Mitgliedsvariablen gegen lokale Variablen
JDK -Quellcode verwendet beispielsweise fast eine lokale Variable, um Elementvariablen in jeder Methode zu akzeptieren
public int vergleicheto (string anotherstring) {int len1 = value.length; int len2 = Anotherstring.Value.Length;Da lokale Variablen im Thread -Stapel der Methode initialisiert werden, während die Mitgliedsvariablen im Heap -Speicher initialisiert werden, ist das erstere offensichtlich schneller. Daher versuchen wir, die Mitgliedsvariablen direkt in der Methode zu verwenden, sondern verwenden lokale Variablen.
3 Absichtlich in Register geladen und zeitaufwändige Operationen außerhalb des Schlosses stellen
Bei Concurrenthashmap ist der Betrieb des Schlosssegments sehr interessant. Es ist kein direktes Schloss, sondern ähnelt einer Spinschloss. Es versucht wiederholt, das Schloss zu erwerben. Während des Erwerbs der Sperre durchquert es die verknüpfte Liste, sodass die Daten zuerst in den Register -Cache geladen werden, wodurch die Bequemlichkeit im Sperrvorgang vermieden wird. Gleichzeitig wird auch der Betrieb neuer Objekte außerhalb des Schlosses platziert, um zeitaufwändige Vorgänge im Schloss zu vermeiden
Final V Put (K Key, Int Hash, V Value, nur boolean nur IfababSent) { /** Bevor Sie in dieses Segment schreiben, müssen Sie zuerst die ausschließliche Sperre des Segments erhalten. Es ist nicht, Lock () zu erzwingen, sondern*/ Hashentry <K, v> node = trylock ()? NULL: ScanandlockForput (Schlüssel, Hash, Wert); scanandlockForput () Quellcode
private Hashentry <K, v> scanandlockForput (K Key, int Hash, V -Wert) {Hashentry <k, v> first = unternehmungsForHash (this, Hash); Hashentry <k, v> e = zuerst; Hashentry <k, v> node = null; int retries = -1; // negativ beim Auffinden von Knoten // Looping, um eine Sperre zu bekommen, während (! trylock ()) {Hashentry <k, v> f; // Um zuerst nach unten zu überprüfen, wenn (return <0) {if (e == null) {if (node == null) // Spekulativ einen Knoten erstellen // Das Hash -Bit hat keinen Wert, erstellen Sie ein neues Objekt und müssen Sie nicht zur Sperre der Put () -Methode erstellen, um eine neue NODE = New Hashentry <k, v> (Hash, Schlüssel, Schlüssel, Schlüssel, Schlüssel, Schlüssel, Schlüssel, Schlüssel, Schlüssel, Schlüssel, nötig) zu erstellen. Wiederholungen = 0; } // Der Hash -Positionschlüssel ist der gleiche und degeneriert in ein Spin -Sperre. sonst // Die Wiederholungen können die verknüpfte Liste automatisch in den Cache e = E.Next lesen; } // Bei Wiederholungen> 0 wird es zu einem Spinschloss. Wenn die Anzahl der Wiederholungen max_scan_retries (Single Core 1 Multi-Core 64) überschreitet, schnappen Sie es natürlich nicht die blockierende Warteschlange und warten Sie auf das Sperre // lock () die Blockierungsmethode, bis es nach dem Erhalt des Schlosses zurückgegeben wird. brechen; } else if if ((retries & 1) == 0 && // Es gibt zu diesem Zeitpunkt ein großes Problem, dh neue Elemente geben die verlinkte Liste ein und werden zu einem neuen Header //. Die Strategie hier ist also, dass es äquivalent ist, durch die Methode scanandlocke zu gehen (f = Eintriebsforhash (this, Hash)! // neu übertrieben, wenn der Eingang die Wiederholung geändert hat = -1; }} returnknoten;} 4 Sie können es zuerst verwenden, um die Objektgleichheit zu bestimmen ==
Wenn Sie beurteilen, ob die Objekte gleich sind, können Sie zuerst == verwenden, da == direkt die Adressen vergleicht, die sehr schnell sind, während Equals die meisten Objektwerte vergleichen, was relativ langsam ist. Wenn möglich, können Sie a == b || verwenden A.Equals (b), um zu vergleichen, ob die Objekte gleich sind.
5 Über transient
Transient wird verwendet, um die Serialisierung zu verhindern, aber das interne Array im HashMap -Quellcode wird als transient definiert.
/*** Die Tabelle, die bei Bedarf geändert wurde. Die Länge muss immer eine Kraft von zwei sein. */ transienter Eintrag <k, v> [] table = (Eintrag <k, v> []) leer_table;
Dann können nicht die Schlüsselwertepaare im Inneren nicht serialisiert werden? Ist es nicht unmöglich, mit HashMap im Netzwerk zu übertragen? Tatsächlich ist es nicht.
Effektiver Java 2nd, Item75, Joshua erwähnte:
Betrachten Sie beispielsweise den Fall einer Hash -Tabelle. Das physische
Darstellung ist eine Folge von Hash-Eimer, die den Schlüsselwert enthalten
Einträge. Der Eimer, in dem sich ein Eintrag befindet, ist eine Funktion des Hashs
Code seines Schlüssels, der im Allgemeinen nicht garantiert ist
Von der JVM -Implementierung bis zur JVM -Implementierung. In der Tat ist es nicht einmal
garantiert vom Lauf bis zum Run garantiert. Daher akzeptieren Sie die
Standard -serialisierte Form für eine Hash -Tabelle würde eine schwerwiegende darstellen
Insekt. Serialisierung und Deserialisierung des Hash -Tisches könnte eine ergeben
Objekt, dessen Invarianten ernsthaft korrupt waren.
Wie versteht man? Schauen Sie sich hashmap.get ()/put () an, um zu wissen, dass das Lesen und Schreiben auf Object.hashCode () basiert, um zu bestimmen, aus welchem Eimer lesen/schreiben soll. Object.hashCode () ist eine native Methode, die in verschiedenen JVMs unterschiedlich sein kann.
Speichern Sie beispielsweise einen Eintrag in HashMap, der Schlüssel ist die Zeichenfolge "String". Im ersten Java -Programm beträgt der HashCode () von "String" 1 und der Bucket Nummer 1 wird gespeichert; Im zweiten Java -Programm kann der HashCode () von "String" 2 sein und der Eimer Nummer 2 wird gespeichert. Wenn die Standardserialisierung verwendet wird (Eintrag [] -Tabelle ist nicht vorübergehend), importiert HashMap das zweite Java -Programm durch Serialisierung aus dem ersten Java -Programm, seine Speicherverteilung ist dieselbe, was falsch ist.
Wenn Sie beispielsweise einen Eintrag von Schlüsselwertpaaren in HashMap speichern, Key = "Fang Laosi", ist im ersten Java-Programm der Hashcode () von "Fang Laosi" 1 und die Tabelle [1] wird gespeichert. OK, jetzt wird es an ein anderes JVM -Programm übergeben, der HashCode () von "Fang Laosi" kann 2 sein, also gehen Sie in die Tabelle [2], um es zu erhalten, und das Ergebnis existiert nicht.
Das aktuelle Reading -und WriteObject von HashMap wird zum Ausgabe/Eingangsinhalt und zum Regenerieren von HashMap verwendet.
6 Verwenden Sie keinen Char
char ist in utf-16 in java codiert und ist 2 bytes, und 2 Bytes können nicht alle Zeichen darstellen. Die 2 Bytes werden als BMP bezeichnet und der andere wird als hohe Ersatz- und niedrige Ersatz- und Ersatzkörper bezeichnet, um einen 4-Byte-Charakter zu bilden, der durch Schreiben dargestellt wird. Zum Beispiel Indexof im String -Quellcode:
// Hier ist ein Int, um ein Zeichen zu akzeptieren, um die Beurteilung des Bereichs Public int indexof zu erleichtern (int ch, int vonIndex) {endgültig int max = value.length; if (von iNdex <0) {fromindex = 0; } else if (von iNidEx> = max) {// Hinweis: FromIndex könnte in der Nähe von -1 >>> 1 sein. Return -1; } // im BMP -Bereich if (ch <characy.min_supplementary_code_point) {// Die meisten Fälle verarbeiten (CH ist ein BMP -Codepunkt oder einen negativen Wert (ungültiger Codepunkt)) endgültig char [] value = this.value; für (int i = von iNdex; i <max; i ++) {if (value [i] == ch) {return i; }} return -1; } else {// Ansonsten wechseln Sie zur Vier-Byte-Urteilsmethode return indexofSupplementary (CH, von INDEX); }}Daher kann Javas Zeichen nur die BMP -Teilzeichen in UTF16 darstellen. Für teilweise erweiterte Charakter -Sets von CJK (China, Japan und Südkorea einheitlich) können sie nicht ausgedrückt werden.
Zum Beispiel kann char nicht dargestellt werden, außer dem ext-a-Teil in der folgenden Abbildung.
Darüber hinaus gibt es ein weiteres Sprichwort, dass Sie Char verwenden sollten. Verwenden Sie keine String für das Passwort. String ist eine Konstante (dh sie kann nach der Erstellung nicht geändert werden) und wird im konstanten Pool gespeichert. Wenn andere Prozesse den Speicher des Vorgangs ablegen können, wird das Kennwort durchgesickert, wenn der konstante Pool abgeladen wird, und char [] kann andere Informationen zur Änderung schreiben, was bedeutet, dass das Risiko des Verlassens des Kennworts verringert wird.
Aber ich persönlich denke, Sie können den Speicher abwerfen. Kann ein Char in der Lage sein, dies zu verhindern? Es sei denn, die String wird nicht im konstanten Pool recycelt und wird von anderen Threads direkt aus dem konstanten Pool gelesen, ist sie wahrscheinlich sehr selten.
Zusammenfassen
Das obige ist der gesamte Inhalt dieses Artikels. Ich hoffe, dass der Inhalt dieses Artikels einen gewissen Referenzwert für das Studium oder die Arbeit eines jeden hat. Wenn Sie Fragen haben, können Sie eine Nachricht zur Kommunikation überlassen. Vielen Dank für Ihre Unterstützung bei Wulin.com.