linux + java + suceso paranormal

B

Esto es de lo más raro que he visto nunca. Estoy empezando a programar más en serio en JAVA bajo linux, y ya empiezo a encontrar problemas muy muy extraños.

Que diferencia hay entre estas dos expresiones para que cuando se cumpla la condición se salga del bucle?

while(!pc.gpsconnected){}

while(!pc.gpsconnected){System.out.print("");}

Mientras que en la primera en cuanto se cumple la condición no sale nunca.... (da igual las expresiones que ponga dentro, he probado de todo), en la segunda si meto algun System.out entonces en cuanto se cumple la condición, esta vez si sale del bucle u_U. Lo encontré por casualidad depurando con prints. La cuestión es que no debería afectar para nada que el bucle estuviera vacío.

Estoy bajo la JRE 1.6.07.0 (AMD 64bits), y la verdad es que me está llevando de cabeza.

La aplicación es un GPS que he montado, está leyendo del puerto serie de un conversor 232-USB (dev/ttyUSB0). Entonces hay un JComboBox que en cuanto seleccionas uno de los puertos y se conecta satisfactoriamente, pone el flag de la condición a True y a correr...... solo si pongo un print dentro del bucle u_U

Teneis alguna noticia o algo de comportamientos raros de java bajo linux?

Este mismo programa escrito bajo windows no da ningún problema.

pd: un apunte por si sirviera de algo, el while esta dentro del run de un thread.

pd2: Podria hacer un wait, pero como hago el notify? , el objeto pc (donde esta el flag) es otra clase heredada de JPanel creado en el mismo thread

B

Leyendome a mi mismo (xDD), veo que no esta muy clara la explicacion, el resumen es:

Un bucle while que solo "mira la condicion" si dentro hay un print.

Daves

No soy un experto, pero hacer un while sin nada dentro del bloque ni de la condición (véase asignar un nuevo valor a la variable de la condición, un "=" o algo así), puede ser que el compilador se lo salte por el forro :/

No sé, yo nunca he hecho Whiles vacíos para... qué? xD

Edit: Vale, es obvio que para esperar a algo, pero en este caso lo que tendrás que hacer es que algún evento del "gpsconnect" ese sea el que avise al programa de qué hacer a continuación. Igual es manía mía, pero eso de hacer whiles que esperan nunca me gustó xd

B

#3

A ver si me das alguna idea xD, te pongo la estructura en "alto nivel" del tema de la espera.

public void run()
{
Createmenu();   <-- Aqui hay un box, dentro del panel pc(viene de portchooser) que muestra los puertos disponibles, y cuando seleccionas uno y se conecta satisfactoriamente, se levanta un flag de "conected" (pc.gpsconnected).

while(!pc.gpsconnected){}    

- Asignamos los streams de subida y bajada a una clase de lectura (es por eso que hay que esperar).

while(true)
 {
- La clase de lectura gestiona el puerto y pasa la informacion que necesiten a las clases consumidoras.
 }
}


main
{
gps = new GPSconsole();
gps.start();
}
B

Me autorespondo de nuevo, que no lo habia puesto.

En modo depuracion, el programa se ejecuta correctamente u_U

Khanser

Solo pueden pasar 2 cosas, que java en linux tenga un no-bucles-infinitos-mode y cuando detecta un bucle tan simple que va a provocar eso, se lo salta en plan guay, o que la condición sea true :3

PD:No, no me he leido todo xD

B

#6

Nada tranqui xD

El problema no es que se lo salte, es que no evalua la condicion. Pero lo que me llama aun mas la atencion, es que si lo lanzo en modo depuracion (estoy usando eclipse), entonces sin problemas.

Al final, he metido un System.out.print(""); dentro del bucle y ya le hace caso.

LOc0

Juntando:


-Este mismo programa escrito bajo windows no da ningún problema.

-Que java en linux tenga un no-bucles-infinitos-mode y cuando detecta un bucle tan simple que va a provocar eso, se lo salta en plan guay

-Pero lo que me llama aun mas la atencion, es que si lo lanzo en modo depuracion (estoy usando eclipse), entonces sin problemas.

Yo tb me decanto porque es cosa de la máquina virtual que "optimiza" mal el bytecode cargándose bucles que considera infinitos sin serlo...

Chapucilla y a correr.

Salu2 ;)

Daves

#4

Pues así a grandes rasgos, la idea sería que ese flag que se levanta cuando conecta pudiera hacer algo más además de eso, aunque no sé si es posible. Lo suyo es que cuando se conecte llames a otra función (método) que haga todo lo de dentro del while(!pc.gpsconnected){}

Si esto no es posible, lo que yo haría sería controlar específicamente en qué situaciones se debe chequear el estado de la conexión (comprobar si gpsconnected= true), ya que de otra forma estás dejando un while correr sin fin y pudiera darse el caso de que nunca termine. Que ésto nos da igual siempre que no nos importe que el programa no sea muy correcto, claro está xD
Si es algo más serio no me daría el lujo de dejar "posibles" bucles infinitos por ahí en ejecución.

salu2

B

#9

Dentro del while no hay nada, es una espera, un semaforo para que el thread no siga corriendo.

El problema es que no hacen falta funciones ni nada, simplemente notificarle al thread que ya puede continuar....... la movida esta que ese es el primer thread que se crea y no hay ningun otro que pueda notificarle (hacer un thread solo para un Combobox es tonteria xD).

No es dejar bucles infinitos por ahi, es la iniciacion del programa, si no se conecta, no se inicia. Es un thread, el programa esta corriendo y chequeandose en otros threads a la vez (si no, no podria seleccionar ningun puerto a mano xD).

Si lo piensas, no es infinito xD, si la condicion no se cumple, no tiene sentido seguir ese thread, ya que asignaria streams nulls etc . Mira la "linea 8" del codigo.

pd: El chequeo de si el puerto esta conectado es la condicion del while ¬¬.

Aun asi, muchisimas gracias por el interes y tu respuesta :P

pd2: Esta solucionado, el problema viene que tengo muchas clases escritas de anteriores programas y voy reutilizando. He reescrito la clase "portchooser" ya preparandolo para ethernet en un futuro y sin problemas ya.

#8

El detalle de la depuracion sin problemas es lo que me ha hecho "decidir" finalmente que es problema de la JVM xD, asi que chapucilla y a correr.

G

No sé si esto servirá pero:

No es mas fácil que createmenu devuelva un boolean (Y que te haga de flag de la conexión)y lo metas en un if-else.

:?

B

#11

Createmenu no es una funcion que haga una operacion y devuelva un valor xD. Ahi dentro se crean todos los paneles, labels etc.

No es programacion "secuencial", no se si lo he recalcado, pero el programa no es el que selecciona el puerto, es el usuario (yo xD), el que selecciona a mano de una lista de un box.

En pocas palabras, el programa siempre ha de pararse hasta que el usuario escoja el puerto.

Lo que he hecho al final, es reescribir el codigo, la eleccion del puerto estaba en otra clase (reutilizada). Asi que he añadido la creacion del menu de la seleccion de puerto donde todas las demas, asi no hace falta ningun flag. Directamente si se selecciona un puerto, el thread se activa. (mas o menos lo que tu dices aunque sin necesidad de ninguna condicion xD)

Antes, como venia de otra clase, el thread se iniciaba y tenia que esperar a la otra clase (flag). Ahora integrado ese menu de seleccion de puerto en el thread, ya no existe ese problema.

Daves

Ciertamente, si esto es multi-thread no habrá problemas de que el programa se quede clavado en cierto punto, pero aún así nunca me gustó hacer ese tipo de whiles xD

De todas formas viendo que el programa está orientado a controlar temas más de hardware, puede que sea una práctica común, aunque yo no tengo mucha experiencia en ello.

Por lo que comentáis, al final parece que es tema de la máquina virtual en linux, así que, lo que se ha hecho toda la vida, "chapucilla" y a pensar en otra cosa :P

MaKi

Si estás sobre un thread ...
while(!pc.gpsconnected)
{
Thread.sleep(10); //faltan try-catch
}

Así no te comes el 100% de la cpu.
Ya es un poco chapuza la espera activa (lo suyo es que el hilo se valla a dormir y el SO le despierte), pero si no tienes otra forma de hacerlo al menos mete algún sleep.

Un saludo

B

#14

No se puede despertar el hilo pq es el unico activo y nadie le puede notificar xD, habria que reescribir todo el codigo, que voy reutilizando clases.

Y sobre meter un sleep, interesa que sea lo antes posible la validacion, aun asi he incluido el sleep y creeme que la diferencia de consumo de la cpu es minima xD

De todas maneras, ya reescribi el codigo y esa espera ha desaparecido.

Usuarios habituales