Ne “rien”, alors que “condition”
Lors de la navigation sur le code pour Java 8 version de ForkJoinPool(qui a un peu de changements intéressants à partir de Java 7) j'ai couru à travers cette construction (ici):
do {} while (!blocker.isReleasable() &&
!blocker.block());
J'ai du mal à comprendre pourquoi vous l'écrire comme ça au lieu de simplement
while (!blocker.isReleasable() &&
!blocker.block());
Est-ce juste une sémantique et la lisibilité de choix, puisque vous avez pu lire la première construction que do "nothing" while "conditions"
? Ou est-il un avantage supplémentaire que je suis absent?
Vous devez vous connecter pour publier un commentaire.
Si vous lisez les commentaires au début du fichier, juste en dessous de la déclaration de la classe, il y a une section qui explique l'utilisation de cette construction:
while
version?do {} while()
évite un JIT, l'optimisation de lawhile()
utilise. L'tandis que les états sont sémantiquement équivalentes, de sorte que la différence doit être dans la mise en œuvre de la JVM.while
boucle a été utilisé tous. Je pense que les raisons sont plutôt ceux de la réponse par Erik Vesteraas, à savoir 1. La clarté et la la lisibilité (!), et 2. Les petits bytecode (1 octet 1 octet).ForkJoinPool
fait un usage intensif decompareAndSwap...
desun.misc.Unsafe
et la plupart des occurrences dedo {} while (...)
dansForkJoinPool
peut — comme mentionné par d'autres réponses — être expliqué par ce commentaire sous la rubrique Style notes:Le choix de l'utilisation d'écrire un
while
-boucle dont le corps est vide commedo {} while (condition)
semble cependant être un surtout stylistique choix. C'est peut-être plus clair dansHashMap
, ce qui est arrivé à être mis à jour en Java 8.Dans Java 7
HashMap
vous pouvez trouver ceci:Bien que le code autour d'elle aussi a changé, il est clair que le remplacement, dans Java 8 est-ce:
La première version a la faiblesse que si le seul point-virgule qui est arrivé à être supprimé, il serait de changer le sens du programme en fonction sur la ligne suivante.
Comme on le voit ci-dessous, le bytecode généré par
while (...) {}
etdo {} while (...);
est légèrement différente, mais pas de la façon qu'devrait influer sur quoi que ce soit quand exécuter.De code Java:
Code généré:
En laissant de côté toute possibilité de les avantages de performance, il est clair que l'avantage de la lisibilité.
Avec
while (X) ;
le point-virgule de fin n'est pas toujours évident au premier coup d'œil, vous pouvez être confus en pensant que la déclaration suivante ou déclarations sont à l'intérieur de la boucle. Par exemple:Il serait très facile de mal interpréter les ci-dessus comme ayant si l'instruction à l'intérieur de la boucle, et même si vous n'avez bien lu, il serait facile de penser que c'était une erreur de programmation et le si doit être à l'intérieur de la boucle.
Avec
do {} while(X);
mais il est tout de suite un coup d'œil évident qu'il n'existe pas de corps de la boucle.while (x==process(y)) {}
? Je pense que ce serait presque aussi clair que de l'do ... while()
solution.do {} while
de la construction des mots-clés entre les crochets, elle rend la séparation plus propre. Même dans cet exemple simple, nous avons déjà 4 crochets les uns après les autres)){}
- vous peut facilement voir que ce nombre pourrait augmenter à mesure que le si devient plus compliqué...il est donc plus facile de ne pas remarquer la{}
avec tous les autres.Si vous allez lire le commentaire ci-dessus le code, Il est mentionné que...
Si l'appelant n'est pas un
ForkJoinTask
, cette méthode est sur le plan comportemental équivalent àC'est juste une autre forme pour mettre en œuvre le code ci-dessus dans le reste de la partie...!!
Dans Style notes il est mentionné que,
Et si vous allez voir la mise en œuvre de ManagedLocker#isReleasable, C'est la mise à jour de la serrure et retourne
true
si le blocage est inutile.Interprétation :
Vide tandis que les boucles sont utilisées pour fournir une interruption jusqu'à ce qu'une certaine condition de réinitialisation de vrai/faux.
Ici,
do { } while(!...)
est un bloqueur/interruption jusqu'à ceblocker.block()
seratrue
quandblocker.isReleasable()
estfalse
. Boucle continuera de l'exécution enblocker
n'est pas libérable (!blocker.isReleasable()
) etblocker
n'est pas bloqué !! L'exécution de la boucle dès queblocker.block()
sera définie sur true.Noter que,
do{ } while(...)
n'est pas le CAS de la variable, mais il garantit que le programme va attendre jusqu'à ce que la variable est mise à jour (force d'attendre jusqu'à ce que la variable est mise à jour).while(!cas...)
ne serait pas forcer une mise à jour? Qu'il y a une réelle différence technique, comme indiqué par le pseudo-code? Je commence à me demander si en regardant isReleasable est une distraction, comme il y a beaucoup d'endroits où il est utilisé pour des CAS effectivement-les variables comme ceci:do {} while (!U.compareAndSwapLong(...));
isReleasable()
est une distraction, l'interprétation donnée à modifier.while(!cas...);
serait en mesure de forcer une mise à jour sur un CompareAndSwap-variable, ou sido {} while (!cas...);
est nécessaire, c'est à dire s'il existe une réelle différence technique ou pas.do{}
activer cette interruption?do{}while(...)
permet d'interruption, il peut être fait avecwhile() { }
aussi. et pour le byte-code, vous pouvez Vous référer Erik réponse, en ce modèle supplémentairegoto
n'est pas nécessaire en raison deifeq
instruction est là, au lieu deifne
... je n'ai jamais dit quedo{}
sont utilisés pour permettre d'interruption !! 😉 😀while(...);
etdo{}while(...);
dans le byte code. Un seul saut inconditionnel moins.Vous pouvez facilement faire quelque chose comme ceci avec: