• Sábado 21 de Septiembre de 2024, 16:03

Autor Tema:  Calcular Retardos  (Leído 2683 veces)

jpaler

  • Miembro MUY activo
  • ***
  • Mensajes: 479
    • Ver Perfil
Calcular Retardos
« en: Lunes 22 de Mayo de 2006, 17:20 »
0
Hola muchachos !!!!

...,¿alguno de ustedes sabe como obtener la velocidad del procesador
en java?

...,¿y sabe mas o menos como calcular un retardo basado en milisegundos
a partir de esa velocidad?

---------------------------------------------

es q tengo un inconveniente al calcular los retardos de manera comun y
corriente como estos deberia ser calculados, miren:

Código: Text
  1.  
  2.      public void delay(long  timeOut){
  3.          while ( ( timeOut > 0 ) && ( puertoSerial.estaOcupado() ) ) {
  4.              try {
  5.                  Thread.sleep( 10 );
  6.                  //this.wait(10);
  7.              }
  8.              catch ( InterruptedException e ) {}
  9.              timeOut--;
  10.          }
  11.          return;
  12.     }
  13.  
  14.  

con este metodo, si yo le mandara: delay(100);
me deberia esperar un tiempo maximo de 1 seg.  antes de retornar.
o menos tiempo, en caso de q el puerto serial se desocupe antes de 1 seg.

...,pero no, no espera nada, es como si el metodo sleep/wait no cumpliera
su funcion.

alguien me dijo q era por la prioridad q el propio compilador le da a los
ciclos (for, while, do-while), osea, q como esta dentro de un while, la
jvm nisiquiera me determina el sleep y simplemente se dedica a seguir el ciclo.

y le creo, por q no es la primera ves q me pasa, tambien he intentado
hacer q se actualize un JProgresssBar dentro de un ciclo (poniendo un retardo)
y tampoco la actualiza, lo q hace es terminar el ciclo y luego pinta el JProgressBar.
NO ES ESTO ALGO RARO.

--------------------------------

entonces, he decidido calcular yo mismo los retardos a razon de la
velocidad del procesador y basandome en ciclos repetitivos.



les agradeceria cualquiera idea q tengan sobre esto.

--------------------------------
Gracias....

silverfox

  • Miembro MUY activo
  • ***
  • Mensajes: 280
    • Ver Perfil
Re: Calcular Retardos
« Respuesta #1 en: Lunes 5 de Junio de 2006, 11:49 »
0
Hola a todos.

Creo recordar que Java no tiene forma de encontrar el procesador, puesto que no está en las propiedades del sistema. La opción que tienes es preguntárselo al SO y obtenerlo con un método nativo.


De todas formas, estás equivocado en una cuestión:

Código: Text
  1. Thread.sleep( 10 );
  2.  

El parámetro de este método está dado en milisegundos, por lo que, si quieres que espere un segundo, tendrás que utilizar sleep(1000).

Yo lo que haría sería otra cosa, ya que estás implementando una espera activa con el sleep y eso baja el rendimiento de tu aplicación.
Utiliza mejor el wait() que tienes comentado. Lo único que tienes que hacer es meter una instrucción notify() o notifyAll() justo antes de la salida del método que se ejecute cuando el puertoSerie quede libre. Los métodos donde tengas el wait y el notify deberían ser synchronized, con eso tendrías que poder manejar la variable puertoSerie de forma exclusiva sin problemas.


Espero que consigas resolverlo. Si tienes más dudas, ya sabes.


Un saludo.


Silverfox

jpaler

  • Miembro MUY activo
  • ***
  • Mensajes: 479
    • Ver Perfil
Re: Calcular Retardos
« Respuesta #2 en: Lunes 5 de Junio de 2006, 14:14 »
0
silver, me inclino mas por la segunda solucion q me das, aunque no la
comprendo mucho:
Código: Text
  1.  
  2. Yo lo que haría sería otra cosa, ya que estás implementando una espera activa con el sleep y eso baja el rendimiento de tu aplicación.
  3. Utiliza mejor el wait() que tienes comentado. Lo único que tienes que hacer es meter una instrucción notify() o notifyAll() justo antes de la salida del método que se ejecute cuando el puertoSerie quede libre. Los métodos donde tengas el wait y el notify deberían ser synchronized, con eso tendrías que poder manejar la variable puertoSerie de forma exclusiva sin problemas.
  4.  

...silver, mi programa debe funcionar asi:
tengo 2 metodos, uno q lee del puerto serial y otro q escribe en el puerto serial.
ambos metodos llaman SIEMPRE a delay y le mandan un parametro tiempo.
y el metodo delay debe RETORNAR UNICAMENTE cuando el puerto serial este
LIBRE, o haya TRANSCURRIDO el tiempo maximo pasado como parametro.
...UNICAMENTE ASI DEBERA DELAY RETORNAR, MIENTRAS TANTO NO.
Y es eso lo q he intentado hacer con la funcion delay(long timeOut).

...compadre, ¿seria posible q usted me explicara como funciona el wait/notify o las diferencias de este con el sleep?
...y me explicaras mejor la solucion q me propones?

GRACIAS SILVER !!!

silverfox

  • Miembro MUY activo
  • ***
  • Mensajes: 280
    • Ver Perfil
Re: Calcular Retardos
« Respuesta #3 en: Lunes 5 de Junio de 2006, 15:40 »
0
Con gusto, jpaler. Vamos a ver...

Si quieres echar un vistazo extenso a estas cosas, mira en algún libro el trabajo con Threads.

Para empezar, supongo que sabes lo que ocurre con un método sincronizado en Java: Cuando llamas a un método clasificado como synchronized, se bloquearán todas las llamadas posteriores a métodos synchronized del mismo objeto por parte de otras hebras. Este bloqueo termina cuando el Thread que llamó retorna del método sincronizado, dejando el camino libre a una de las hebras que entrará en uno de los métodos sincronizados del objeto compartido.

Cuando se hace un sleep, la hebra que llama al método queda ocupando el método, a diferencia de cuando se llama a wait. En el último caso, la hebra queda en estado de suspendida (puedes ver el método suspend de Thread, también deberías repasar el ciclo de vida de una hebra en Java en la documentación o en algún libro similar). Por lo tanto, si usas sleep, puede que la máquina virtual continúe ejecutando la hebra dormida y que, por lo tanto, la otra no avance (con un tiempo de sleep tan corto como ponías en tu ejemplo, seguramente haya pasado eso).

Tal y como lo pones, creo que la opción sería la siguiente:

Código: Text
  1. public synchronized void delay(long timeOut){
  2.     while (puertoSerial.estaOcupado()){
  3.         this.wait(timeOut);
  4.     }
  5.     return;
  6. }
  7.  

pero también tendrás que modificar los métodos que modifiquen la variable ocupado:

Código: Text
  1. public synchronized void setOcupado(boolean busy){
  2.     this.ocupado= busy;
  3.     if (!busy)
  4.         this.notifyAll();
  5. }
  6.  



Cuando se hace el wait, quedarás bloqueado en el método, en espera de que alguien te despierte con un notify. El wait con un parámetro indica un tiempo de espera en milisegundos. Si no se recibe el notify correspondiente en este tiempo, la hebra despertará sola y continuará la ejecución.
Si sólo tienes 2 hebras, en lugar de un while, podrás poner un if y te dará el comportamiento que esperabas. Si tienes más de dos hebras funcionando deberás usar el while, considerando que el notifyAll despierta a todas las hebras que estén dormidas en el wait, pero de las cuales sólo una podrá entrar en el método, las otras tendrían que volver a ejecutar el wait (por eso el while).


Espero que con estos consejos puedas terminar el trabajo sin problemas. Si necesitas alguna cosa más, ya sabes.


Un saludo.


Silverfox

jpaler

  • Miembro MUY activo
  • ***
  • Mensajes: 479
    • Ver Perfil
Re: Calcular Retardos
« Respuesta #4 en: Martes 6 de Junio de 2006, 06:51 »
0
bueno silver.... dejame y doy un respiro y compilo en mi pequeña
mente todo lo q me dijiste...

...¿acaso eres profesor?
sabes explicar muy bien...

Gracias por todo ese monton de info q me acabas de dar....

...,voy a codificar algo de lo q dices y luego te comento listo !!!

jpaler

  • Miembro MUY activo
  • ***
  • Mensajes: 479
    • Ver Perfil
Re: Calcular Retardos
« Respuesta #5 en: Martes 6 de Junio de 2006, 19:37 »
0
silver, estube leyendo en un libro de java2 de javier ceballos y si...
...,efectivamente explica de manera igual lo del sleep y wait.

silver, lo q necesito hacer es:
hacer un metodo q envie/reciba datos por el puerto serial y q reciba un parametro
q indique el tiempo maximo q este (el metodo) puede tardar esperando (en
caso de q el dispositivo al q le va a enviar/recibir datos se encuentre ocupado).

Haciendo una analogia con otros metodos parecidos, te puedo decir q es algo asi como System.in.read().  Este metodo espera hasta q ocurra un evento (entren datos al buffer).
En mi caso yo espero hasta q el dispositivo q esta conectado al puerto serial
me indique q él ya se desocupó (y esto lo hace con la bandera DSR en 1, osea true)
o haya transcurrido el tiempo maximo de espera.



Resumiendo todo, el codigo q tengo es este:

Código: Text
  1.  
  2. public class PuertoSerial{
  3.     /*************************************************************
  4.      *                      DEFINICION DE LOS ATRIBUTOS                        *
  5.      *************************************************************/
  6.     /.../
  7.  
  8.     public PuertoSerial() {
  9.         /.../  
  10.         try {
  11.             this.puerto.addEventListener( new SerialPortEventListener() {
  12.                 public void serialEvent( SerialPortEvent evento ) {
  13.                     cambioBanderaDSR( evento );
  14.                     //DSR es un pin del puerto serial q me indica si el dispositivo q esta
  15.                     //  conectado al puerto esta ocupado.
  16.                     //Es decir, el disp. q se encuentra conectado al pto. serial del pc,
  17.                     //pone esta bandera en 1 para indicarle al pc q esta ocupado y q no lo
  18.                     //  moleste, o lo pone en 0 para decirle q esta listo para recibir un
  19.                     //  comando o para lo q sea.                                            
  20.                 }
  21.             } );
  22.         }
  23.         catch ( TooManyListenersException exc ) {}
  24.         this.puerto.notifyOnDSR(true); //le digo q me notifiquen cuando haya un
  25.                                                      //  cambio de estado en la bandera DSR
  26.     }
  27.  
  28.  
  29.     public synchronized char recibirCaracter( long timeOut ) {
  30.         //Mientras q el disp, conectado al pc este ocupado, esperare a q se desocupe
  31.         // o hasta q transcurra el tiempo maximo de espera (timeOut)
  32.         while ( this.puerto.isDSR() ) {
  33.             try {
  34.                 this.wait( timeOut );
  35.             }
  36.             catch ( InterruptedException e ) {}
  37.         }
  38.         if (this.puerto.isDSR() ) {
  39.             /...LEER CARACTER.../
  40.         }
  41.         return '\n';
  42.     }
  43.  
  44.     public synchronized void enviarCaracter( char c, long timeOut ) {
  45.         //Mientras q el disp, conectado al pc este ocupado, esperare a q se desocupe
  46.         // o hasta q transcurra el tiempo maximo de espera (timeOut)
  47.         while ( this.puerto.isDSR() ) {
  48.             try {
  49.                 this.wait( timeOut );
  50.             }
  51.             catch ( InterruptedException e ) {}
  52.         }
  53.         if (this.puerto.isDSR() ) {
  54.             /...ENVIAR CARACTER.../
  55.         }
  56.         return;
  57.     }
  58.  
  59.  
  60.      /**
  61.       * Este es el metodo q se llama cuando ocurre el evento de cambio de
  62.       * estado de la bandera DSR q es la indica si el disp. conectado al
  63.       * saerial esta o no disponible
  64.       */
  65.      public synchronized void cambioBanderaDSR( SerialPortEvent evento ) {
  66.          if ( evento.getEventType() == SerialPortEvent.DSR ) {
  67.              //Si esto es true, entonces el DSR=1 y el disp. conectado al pto.
  68.              //  serial esta listo.
  69.              // entonces llamo notifyAll para q despierte al wait q llame la ultima ves.
  70.              if ( !evento.getNewValue() ) {
  71.                   this.notifyAll();
  72.              }
  73.          }
  74.      }
  75. }
  76.  
  77.  


...,este es el codigo, q segun lo q tu me dijiste y lo q lei en el libro pude armar,
pero nada silver, no funciona.
..pero se q esto se puede hacer en java, lo q no pense es q me fuera complicar
tanto la vida.

silver, te agradezco q le heches una miradita al codigo, pa' ver q es loq pasa!!!

silverfox

  • Miembro MUY activo
  • ***
  • Mensajes: 280
    • Ver Perfil
Re: Calcular Retardos
« Respuesta #6 en: Miércoles 7 de Junio de 2006, 10:34 »
0
Hola jpaler...

¿Qué error te deja tu código?

Supongo que lo que terminará haciendo es dejar bloqueadas las Threads que utilizas, ¿no?

Fíjate en una cuestión:

Código: Text
  1.  
  2.        while ([B] this.puerto.isDSR() [/B]) {
  3.            try {
  4.                this.wait( timeOut );
  5.            }
  6.            catch ( InterruptedException e ) {}
  7.        }
  8.        if ([B]this.puerto.isDSR() [/B]) {
  9.              //escribe caracteres
  10.        }
  11.  
  12.  
Nunca escribirá caracteres, porque es condición para que salga del bucle que puerto.isDSR= false;

Creo recordar que tenías sólo 2 hebras funcionando, ¿has probado si se envía el notify?

Yo cambiaría lo siguiente:
    Crear un método reservarPuerto:
 
Código: Text
  1.    synchronized reservarPuerto(long timeOutMillis) throws TimeOutException{
  2.         if (puerto ocupado){
  3.              wait(timeOutMillis);
  4.              if (se excedió el tiempo) throw new TimeOutException("Tiempo de espera excedido");
  5.         }
  6.         else {
  7.             ocupado= true;
  8.         }
  9.     }
  10.  
   
    Crear un método devolverPuerto:
Código: Text
  1.     synchronized devolverPuerto(){
  2.         //aqui reseteas todos los flags del puerto y lo pones en modo de espera de comandos
  3.  
  4.         this.notifyAll();  //esta es la última instrucción y despierta a todos los dormidos en el wait, de los cuales el más rápido reservará el puerto
  5.     }
  6.  


En todos los métodos que usen el recurso compartido, será obligatorio reservarlo y liberarlo:

Código: Text
  1. synchronized void escribir puerto(){
  2.     reservarPuerto();
  3.     . . .
  4.     devolverPuerto();
  5.     return;
  6. }
  7.  

Y con esto debería funcionarte sin problemas.


Espero haberme explicado correctamente. Echare un vistazo a algunos libros a ver si puedo recomendarte alguno. De momento, te remito a uno que se llama Concurrent Programming with Java, de Prentice Hall.


Suerte, si tienes más dudas, dilo y trataré de explicarlo mejor.
Un saludo.



Silverfox