switch - ejercicios do while java netbeans
Hacer "nada" mientras "condiciĆ³n" (5)
Mientras navegaba por el código de la versión Java 8 de ForkJoinPool (que tiene algunos cambios interesantes de Java 7), encontré este constructo ( here ):
do {} while (!blocker.isReleasable() &&
!blocker.block());
Estoy luchando con por qué lo escribirías así en lugar de solo
while (!blocker.isReleasable() &&
!blocker.block());
¿Es solo una elección de semántica / legibilidad, ya que puedes leer el primer constructo como do "nothing" while "conditions"
? ¿O hay algún beneficio adicional que me falta?
Dejando de lado los posibles beneficios de rendimiento, existe un claro beneficio de legibilidad.
Con while (X) ;
el punto y coma final no siempre es obvio a primera vista, puede confundirse al pensar que la siguiente declaración o declaraciones están dentro del ciclo. Por ejemplo:
while (x==process(y));
if (z=x) {
// do stuff.
}
Sería muy fácil malinterpretar lo anterior como si tuviera la instrucción if dentro del ciclo, e incluso si lo hubiera leído correctamente, sería fácil pensar que fue un error de programación y que debería estar dentro del ciclo.
Con do {} while(X);
aunque de inmediato queda claro que no hay cuerpo en el circuito.
Puedes hacer algo como esto fácilmente con:
if(true){
//Do nothing ...
}
Si leerá el comentario arriba del código, se menciona que ...
Si la persona que llama no es una ForkJoinTask
, este método es conductualmente equivalente a
while (!blocker.isReleasable())
if (blocker.block())
return;
}
¡Entonces es solo otra forma de implementar el código anterior en la parte else ...!
En notas de estilo se menciona que,
Hay varias ocurrencias del inusual "do {} while (! Cas ...)" que es la forma más simple de forzar una actualización de una variable CAS.
Y si ve la implementación de ManagedLocker#isReleasable , está actualizando el bloqueo y devuelve true
si el bloqueo no es necesario.
Interpretación:
Los ciclos while en blanco se utilizan para proporcionar una interrupción hasta que algunas condiciones se restablezcan a verdadero / falso.
Aquí, do { } while(!...)
es un bloqueador / interrupción hasta que blocker.block()
sea true
cuando blocker.isReleasable()
es false
. Loop continuará la ejecución mientras que el blocker
no se puede !blocker.isReleasable()
) y el blocker
no está bloqueado! La ejecución estará fuera de ciclo tan pronto como blocker.block()
se establezca en verdadero.
Tenga en cuenta que, do{ } while(...)
no actualiza la variable CAS, pero garantiza que el programa esperará hasta que la variable se actualice (forzar a esperar hasta que la variable se actualice).
Si lees los comentarios en la parte superior del archivo, justo debajo de la declaración de la clase, hay una sección que explica el uso de esta construcción:
Style notes
===========
[...]
There are several occurrences of the unusual "do {} while
(!cas...)" which is the simplest way to force an update of a
CAS''ed variable. There are also other coding oddities (including
several unnecessary-looking hoisted null checks) that help
some methods perform reasonably even when interpreted (not
compiled).
ForkJoinPool
hace un uso extensivo de compareAndSwap...
de sun.misc.Unsafe
y la mayoría de las ocurrencias de do {} while (...)
en ForkJoinPool
puede ForkJoinPool
, como se menciona en otras respuestas, mediante este comentario bajo el título Notas de estilo :
* There are several occurrences of the unusual "do {} while * (!cas...)" which is the simplest way to force an update of a * CAS''ed variable.
La opción de usar escribir un while
-loop con un cuerpo vacío como lo do {} while (condition)
parece sin embargo ser una elección principalmente estilística. Esto es quizás más claro en HashMap
, que se actualizó en Java 8.
En Java 7 HashMap
puedes encontrar esto:
while (index < t.length && (next = t[index++]) == null)
;
Si bien gran parte del código que lo rodea también ha cambiado, está claro que el reemplazo en Java 8 es este:
do {} while (index < t.length && (next = t[index++]) == null);
La primera versión tiene la debilidad de que si el único punto y coma que se eliminó cambiaría el significado del programa dependiendo de la siguiente línea.
Como se ve a continuación, bytecode generado por while (...) {}
y do {} while (...);
es ligeramente diferente, pero no de ninguna manera que debería afectar nada cuando se ejecuta.
Código Java:
class WhileTest {
boolean condition;
void waitWhile() {
while(!condition);
}
void waitDoWhile() {
do {} while(!condition);
}
}
Código generado:
class WhileTest {
boolean condition;
WhileTest();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
void waitWhile();
Code:
0: aload_0
1: getfield #2 // Field condition:Z
4: ifne 10
7: goto 0
10: return
void waitDoWhile();
Code:
0: aload_0
1: getfield #2 // Field condition:Z
4: ifeq 0
7: return
}