Préface
C'est assez inactif au cours de cette période, j'ai donc regardé le code source JDK. Un ingénieur général de développement principal peut s'améliorer en lisant un code source. Cet article résume quelques «petits conseils» dans le code source JDK et les partage pour votre référence et votre apprentissage. Je ne dirai pas beaucoup ci-dessous, jetons un coup d'œil à l'introduction détaillée ensemble.
1 i ++ vs i--
Ligne 985 du code source de chaîne, dans la méthode égaux
while (n -! = 0) {if (v1 [i]! = v2 [i]) return false; i ++; }Ce code est utilisé pour juger si la chaîne est égale, mais il y a une chose étrange qui utilise i -! = 0 pour faire des jugements. N'utilisons-nous pas habituellement i ++? Pourquoi utiliser i--? Et le nombre de cycles est le même. La raison en est qu'il y aura une autre instruction après la compilation:
I- L'opération elle-même affectera CPSR (registre d'état du programme actuel). Les drapeaux communs pour CPSR sont n (le résultat est négatif), Z (le résultat est 0), C (transport) et O (débordement). I> 0, peut être directement jugé par le drapeau Z.
L'opération I ++ affectera également CPSR (registre d'état du programme actuel), mais affectera uniquement le drapeau O (avec débordement), qui n'aidera pas dans le jugement de i <n. Par conséquent, une instruction de comparaison supplémentaire est nécessaire, ce qui signifie qu'une autre instruction doit être exécutée pour chaque boucle.
Autrement dit, par rapport à 0, il y aura une instruction de moins. Par conséquent, recyclez I-, haut de gamme, atmosphérique et haut de gamme.
2 variables membre vs variables locales
Le code source JDK utilise presque une variable locale pour accepter les variables des membres dans n'importe quelle méthode, par exemple
public int compareto (String anotherstring) {int len1 = value.length; int len2 = anotherstring.value.length;Parce que les variables locales sont initialisées dans la pile de threads de la méthode, tandis que les variables des membres sont initialisées dans la mémoire du tas, évidemment, la première est plus rapide, nous essayons donc d'éviter d'utiliser des variables membre directement dans la méthode, mais utilisons plutôt des variables locales.
3 Chargement délibérément dans les registres et mettez des opérations longues à l'extérieur de la serrure
Dans ConcurrenthashMap, le fonctionnement du segment de verrouillage est très intéressant. Ce n'est pas une serrure directe, mais est similaire à un verrou de rotation. Il essaie à plusieurs reprises d'acquérir la serrure. Pendant le processus d'acquisition du verrou, il traversera la liste liée, afin que les données soient chargées d'abord dans le cache de registre, en évitant la commodité dans le processus de verrouillage. Dans le même temps, le fonctionnement de la génération de nouveaux objets est également placé à l'extérieur de la serrure pour éviter les opérations longues dans le serrure
Final V put (k key, int hash, V valeur, booléen uniquementIfabsent) {/ ** Avant d'écrire dans ce segment, vous devez d'abord obtenir le verrou exclusif du segment. Il ne s'agit pas de forcer Lock (), mais d'essayer * / hashentry <k, v> node = trylock ()? NULL: ScanAndLockForput (clé, hachage, valeur); Code source ScanandLforput ()
Hashentry privé <k, v> scanandlockForput (k key, int hash, v valeur) {hashentry <k, v> first = entryForHash (this, hash); Hashentry <k, v> e = premier; Hashentry <k, v> node = null; intatries = -1; // négatif lors de la localisation du nœud // en boucle pour obtenir le verrouillage pendant (! trylock ()) {hashentry <k, v> f; // pour revérifier d'abord ci-dessous if (Retries <0) {if (e == null) {if (node == null) // Créer spéculativement nœud // Le bit de hachage n'a pas de valeur, créer un nouvel objet, et pas besoin d'aller à la serrure de la méthode put () pour créer un nouveau nœud = nouveau hashentry <k, v> (hachage, clé, valeur, null); Retries = 0; } // La clé de position de hachage est la même, dégénérée en verrouillage de spin else if (key.equals (e.key)) réplade = 0; else // Les Retries peuvent lire automatiquement la liste liée dans le cache e = e.next; } // Lorsque vous réposez> 0, il devient un verrou de spin. Bien sûr, si le nombre de tentatives dépasse Max_SCan_Retries (multi-core 1-core 64), alors ne l'arrachez pas, entrez la file d'attente de blocage et attendez le verrouillage // lock () est la méthode de blocage jusqu'à ce qu'elle revienne après avoir obtenu le verrou, sinon il accrochera else if (++ Retries> max_scan_retrries) {Lock (); casser; } else if ((Retries & 1) == 0 && // il y a un gros problème pour le moment, c'est-à-dire que de nouveaux éléments entrent dans la liste liée et deviennent un nouvel en-tête // donc la stratégie ici est qu'elle équivaut à la méthode ScanAndLockForput à nouveau (f = entryForHash (this, hash))! = First) {e = first = f; // re-traverse si l'entrée a changé Retries = -1; }} Node de retour;} 4 Vous pouvez d'abord l'utiliser pour déterminer l'égalité de l'objet ==
Lorsque vous jugez si les objets sont égaux, vous pouvez d'abord utiliser == car == compare directement les adresses, ce qui est très rapide, tandis que les égaux comparent le plus de valeurs d'objets, ce qui est relativement lent. Donc, si possible, vous pouvez utiliser un == b || A. Equal (b) pour comparer si les objets sont égaux.
5 À propos du transitoire
Le transitoire est utilisé pour empêcher la sérialisation, mais le réseau interne dans le code source HashMAP est défini comme transitoire.
/ ** * Le tableau, redimensionné si nécessaire. La longueur doit toujours être une puissance de deux. * / entrée transitoire <k, v> [] table = (entrée <k, v> []) vide_table;
Alors les paires de valeurs clés ne peuvent-elles pas être sérialisées? N'est-il pas impossible de transmettre en utilisant HashMap sur le réseau? En fait, ce n'est pas le cas.
Java efficace 2nd, item75, Joshua a mentionné:
Par exemple, considérez le cas d'une table de hachage. Le physique
La représentation est une séquence de seaux de hachage contenant une valeur clé
Entrées. Le seau dans lequel une entrée réside est une fonction du hachage
Code de sa clé, qui n'est pas, en général, garanti d'être le même
de l'implémentation JVM à l'implémentation JVM. En fait, ce n'est même pas
Garanti d'être le même de Run to Run. Par conséquent, acceptant le
Le formulaire sérialisé par défaut pour une table de hachage constituerait un
bogue. Sérialiser et désérialiser le tableau de hachage pourrait produire un
objet dont les invariants étaient sérieusement corrompus.
Comment comprendre? Jetez un œil à Hashmap.get () / put () pour savoir que la carte de lecture et d'écriture est basée sur object.hashcode () pour déterminer à quel seau à lire / écrire. Object.HashCode () est une méthode native, qui peut être différente dans différents JVM.
Par exemple, enregistrez une entrée sur hashmap, la clé est la chaîne "String". Dans le premier programme Java, le HashCode () de "String" est 1 et le baquet numéro 1 est stocké; Dans le deuxième programme Java, le HashCode () de "String" peut être 2 et le numéro de godet 2 est stocké. Si la sérialisation par défaut est utilisée (le tableau Entrée [] ne nécessite pas de transitoire), après ce hashmap importe le deuxième programme Java via la sérialisation à partir du premier programme Java, sa distribution de mémoire est la même, ce qui est faux.
Par exemple, si vous enregistrez une entrée de paire de valeurs clés sur hashmap, key = "fang laosi", dans le premier programme Java, le hashcode () de "fang laosi" est 1 et le tableau [1] est stocké. OK, maintenant il est transmis à un autre programme JVM, le HashCode () de "Fang Laosi" peut être 2, donc vous allez dans le tableau [2] pour l'obtenir, et le résultat n'existe pas.
ReadObject actuel de HashMap et WriteObject sont utilisés pour sortir / entrer le contenu et régénérer HashMap.
6 N'utilisez pas Char
Char est codé dans UTF-16 en Java, et est de 2 octets, et 2 octets ne peuvent pas représenter tous les caractères. Les 2 octets sont appelés BMP, et l'autre est appelé substitution élevée et substitut faible pour former un caractère de 4 octets représenté par le scribdage. Par exemple, indexof dans le code source de chaîne:
// voici un int pour accepter un char pour faciliter le jugement de l'index INT public de la plage (int ch, int fromIndex) {final int max = value.length; if (fromIndex <0) {FromIndex = 0; } else if (FromIndex> = max) {// Remarque: FromIndex peut être proche -1 >>> 1. retour -1; } // Dans la plage de BMP if (ch <caractères.min_supplementary_code_point) {// gère la plupart des cas ici (ch est un point de code BMP ou une valeur négative A // (point de code non valide)) Final char [] value = this.value; for (int i = fromIndex; i <max; i ++) {if (value [i] == ch) {return i; }} return -1; } else {// Sinon, accédez à la méthode de jugement de quatre octets IndexofSupplémentaire (Ch, FromIndex); }}Par conséquent, le char de Java ne peut représenter que les caractères partiels BMP dans UTF16. Pour les ensembles de caractères étendus partiels de CJK (Chine, Japon et Corée du Sud), ils ne peuvent pas être exprimés.
Par exemple, Char ne peut pas être représenté, sauf pour la partie EXT-A de la figure ci-dessous.
De plus, il y a un autre dicton que vous devriez utiliser Char. N'utilisez pas de chaîne pour le mot de passe. La chaîne est une constante (c'est-à-dire qu'elle ne peut pas être modifiée après la création) et sera enregistrée dans le pool constant. Si d'autres processus peuvent vider la mémoire du processus, le mot de passe sera divulgué lorsque le pool constant est vidé et Char [] peut écrire d'autres informations pour changer, ce qui signifie qu'il réduira le risque de divulguer le mot de passe.
Mais je pense personnellement que vous pouvez vider la mémoire. Un char peut-il pouvoir l'empêcher? À moins que la chaîne ne soit recyclée dans la piscine constante et ne soit lue directement à partir du pool constant par d'autres fils, il est probablement très rare.
Résumer
Ce qui précède est l'intégralité du contenu de cet article. J'espère que le contenu de cet article a une certaine valeur de référence pour l'étude ou le travail de chacun. Si vous avez des questions, vous pouvez laisser un message pour communiquer. Merci pour votre soutien à wulin.com.