Hilos en Java(Threads) parte 3

Recordemos lo visto en la segunda parte de Hilos en Java:

- Existen diversos tipos de constructores a partir de los cuales se puede crear un hilo, algunos de los más importantes son:
+ Thread()
+ Thread(objetoRunnable)
+ Thread(objetoRunnable, String nombre)
+ Thread(String nombre)

- Un hilo recién creado e instanciado se encuentra en estado nuevo (new), pasa a estado en ejecución (runnable) cuando se llama a su método start() y se considera muerto (dead) una vez que se completa lo contenido en su método run().

- Para llamar al método start() se necesita una instancia de la clase Thread.

- El método estático Thread.currentThread().getName() se utiliza para saber qué proceso se encuentra en ejecución en un momento determinado.

- Cuando se trata de hilos, muy pocas cosas está garantizadas. Una de ellas es que cada hilo se iniciará y se ejecutará hasta que se complete pero no en un orden específico ni sin interrupciones.

- Solamente se puede llamar una vez al método start() de un hilo en particular, de lo contrario se obtiene una excepción de tipo java.lang.IllegalThreadStateException.

Sigamos pues con los hilos en Java.

Más info tras el salto...




El programador de hilos::

En la máquina virtual de Java existe algo que llamamos el programador de hilos que es el encargado de decidir qué hilo es el que se va a ejecutar por el procesador en un momento determinado y cuándo es que debe de parar o pausar su ejecución. Asumiendo que se tiene un equipo de un solo procesador, solo un proceso puede estar corriendo en un momento dado, como lo hemos mencionado anteriormente, la idea de multi-proceso o multithreading es meramente aparente. Para que un hilo sea elegible para ser ejecutado, este debe de estar en estado en ejecución (runnable), si se encuentra en cualquier otro estado no podrá ser elegible por el programador de hilos. Es importante tomar en cuenta que...

"El orden en que un hilo en estado de ejecución es escogido por el programador de hilos no es garantizado".

...aunque no podemos controlar al programador de hilos, en algunas ocasiones podemos influenciarlo mandando a llamar algunos métodos contenidos en la clase java.lang.Thread.


Los métodos de la clase java.lang.Thread::

Algunos métodos de esta clase nos pueden ayudar a influenciar al programador de hilos a tomar una decisión sobre qué hilo ejecutar en qué momento. Los métodos son los siguientes:

+ public static void sleep(long milisegundos) throws InterruptedException
+ public static void yield()
+ public final void join() throws InterruptedException
+ public final void setPriority(int nuevaPrioridad)

Nota: el método sleep() y join() tienen versiones sobrecargadas que no hemos mencionado.

Algunos métodos de la clase java.lang.Object::

Recordemos que toda clase en Java hereda de la clase Object, por lo tanto, cualquier objeto de cualquier tipo tiene todos los métodos de la clase Object por defecto. En este caso analizaremos algunos de ellos que nos son útiles en el manejo de hilos:

+ public final void wait() throws InterruptedException
+ public final void notify()
+ public final void notifyAll()

El método wait() define 3 versiones sobrecargadas, incluyendo la mencionada anteriormente.

Antes de mencionar el comportamiento de los métodos anteriormente mencionados, analicemos algunos estados más en los que un hilo se puede encontrar y sus respectivas transiciones.

Estados de los hilos y transiciones::

Ya hemos visto 3 estados de los hilos - nuevo, en ejecución y muerto - pero hay algunos otros bastante importantes. Analicemos cada uno de ellos:

- Nuevo (new): Este es el estado en que un hilo se encuentra después de que un objeto de la clase Thread ha sido instanciado pero antes de que el método start() sea llamado.

- En ejecución (runnable): Este es el estado en que un hilo puede ser elegido para ser ejecutado por el programador de hilos pero aún no está corriendo en el procesador. Se obtiene este estado inmediatamente después de hacer la llamada al método start() de una instancia de la clase Thread.

- Ejecutándose (running): Este es el estado en el que el hilo está realizando lo que debe de hacer, es decir, está realizando el trabajo para el cual fue diseñado.

- Esperando/bloqueado/dormido (waiting/blocked/sleeping): Es el estado en el cual el hilo está vivo aún pero no es elegible para ser ejecutado,es decir, no está en ejecución pero puede estarlo nuevamente si algún evento en particular sucede. Por ejemplo, un hilo puede estar durmiendo por que en el código se le ha pedido que lo haga pero pasa a estado en ejecución cuando el tiempo que se le pidió dormir ha expirado.

- Muerto (dead): Un hilo está muerto cuando se han completado todos los procesos y operaciones contenidos en el método run(). Una vez que un hilo ha muerto NO puede volver nunca a estar vivo, recordemos que no es posible llamar al método start() más de una vez para un solo hilo.

Prevenir la ejecución de un hilo::

:Hilo Durmiendo (sleeping):

El método sleep() es un método estático de la clase Thread. Generalmente lo usamos en el código para pausar un poco la ejecución de un proceso en particular forzándolo a dormir durante un tiempo determinado. Para forzar un hilo a dormir podemos usar un código parecido a lo siguiente:

try{
Thread.sleep(5*60*1000); //Duerme durante 5 minutos
}catch(InterruptedException ex){}

Normalmente cuando llamamos al método sleep() encerramos el código en un try/catch debido a que dicho método arroja una excepción.

El hecho de que un hilo deje de dormir, no significa que volverá a estar ejecutándose al momento de despertar, el tiempo especificado dentro del método sleep() es el mínimo de tiempo que un hilo debe de dormir, aunque puede ser mayor. De igual manera se debe de tomar en cuenta que el método sleep() es estático, es decir, solo hay uno para toda la clase Thread, por lo tanto, un hilo no puede poner a dormir a otro, el método sleep() siempre SIEMPRE afecta al hilo que se encuentra ejecutando al momento de hacer la llamada.

:Prioridades de hilo y el método yield():

Para entender el método yield(), debemos entender las prioridades de los hilos. Un hilo siempre corre con una prioridad, normalmente va de 1 a 10, debido a esto, el programador de hilos generalmente utiliza su programación basada en prioridades. Un hilo de menor prioridad que se encuentra ejecutando usualmente será desplazado al estado en ejecución para que un hilo de mayor prioridad pueda ejecutarse. De cualquier manera, nunca debes de basar el funcionamiento de tu aplicación basado en las prioridades de los hilos.

Para establecer la prioridad de un hilo debemos hacer algo parecido a lo siguiente:

HiloRunnable h = new HiloRunnable();
Thread t = new Thread(h);
t.setPriority(7);
t.start();

Algunas máquinas virtuales no son capaces de reconocer 10 valores diferentes de prioridad, lo que causa un problema al momento de la ejecución, debido a ello, la clase Thread tiene 3 constantes (variables estáticas y finales) que definen un rango de prioridades de hilo:

+ Thread.MIN_PRIORITY (1)
+ Thread.NORM_PRIORITY (5)
+ Thread.MAX_PRIORITY (10)

:El método yield():

El método yield() tiene la función de hacer que un hilo que se está ejecutando de regreso al estado en ejecución(runnable) para permitir que otros hilos de la misma prioridad puedan ejecutarse. Sin embargo, el funcionamiento de este método (al igual que de los hilos en general) no está garantizado, puede que después de que se establezca un hilo por medio del método yield() a su estado en ejecución(runnable), éste vuelva a ser elegido para ejecutarse. El método yield() nunca causará que un hilo pase a estado de espera/bloqueado/dormido, simplemente pasa de ejecutándose(running) a en ejecución(runnable).

:El método join():

El método no estático join() permite al hilo "formarse en la cola de espera" de otro hilo. Si tienes un hilo B que no puede comenzar a ejecutarse hasta que se complete el proceso del hilo A, entonces querrás que B se forme en la cola de espera de A. Esto significa que B nunca podrá ejecutarse si A no completa su proceso. En código se utiliza así:

Thread t = new Thread();
t.start();
t.join();

Existe una versión sobrecargada de join() que puede incluir el tiempo en milisegundos, por ejemplo si llamamos a t.join(5000), significa que el hilo que queremos ejecutar debe esperar a que el hilo que se está ejecutando en este momento termine, pero si tarda más de 5 segundos entonces debe dejar de esperar y entrar en estado de ejecución(runnable).

Hasta aquí le dejamos con la tercera parte...

Más sobre programación en Java aquí.

15 comentarios:

  1. Anónimo dijo...:

    jejeje shida la informacion me gusto y me aclaro la duda que tenia acerca de los estado del hilo...

    gracias

  1. Anónimo dijo...:

    es un excelente explicacion sobre Thread, les agradezco.

  1. jgui dijo...:

    Muchas gracias, me has ayudado a solucionar un bug que me estaba volviendo loco por más de dos horas!!!

  1. Eduardo dijo...:

    Muchas gracias me ayudo a entender más sobre el método join(); ^_^arigato

  1. Ya'akov dijo...:

    Conceptos claros y muy entendibles. Gracias por el post.

  1. Vitucho dijo...:

    Muy bien post amigo!

  1. Anónimo dijo...:

    Pero cómo sé a qué hilo está esperando el que le coloco join()?

    Si quiero que el hilo A espere a que finalice B, cómo lo escribiría?

  1. Alex dijo...:

    Es una copia tel tema de Threads del libro SCJP6 de Mcgraw hill

  1. Anónimo dijo...:

    Muchas gracias por la info, excelente blog

  1. Anónimo dijo...:

    Hola quisiera que me ayudes!!! la verdad soy novata en java y pues no se como solucionar mi problemita!!!
    Mira estoy trabajando con formularios y quiero hacer una pausa a la hora de mostrar el resultado por medio de un thread Sleep(la sintaxis esta correcta), el detalle esta en que la pausa la hace antes de mostrar el resultado y no despues despues como yo quiero y la verdad no se en que consiste.
    Soy Mary, te envie un correo hace un rato espero que puedas ayudarme lo mas pronto posible, mil gracias
    private void jTxtNominaLaboralKeyReleased(java.awt.event.KeyEvent evt) {

    if (evt.getKeyCode() == 10) {
    //En esta parte valido que mi caja de texto no este vacia y que solo se introduscan numeros
    if ((jTxtNominaLaboral.getText().length() == 0) || (!isNumeric(jTxtNominaLaboral.getText()))) {
    JOptionPane.showMessageDialog(null, "Introduce tu número de nomina");
    jTxtNominaLaboral.setText("");
    jTxtNominaLaboral.requestFocusInWindow();
    } else {
    //Aqui estan algunas instrucciones
    try {

    //En esta linea me hace la pausa y qui no debe ser
    c.num_nomina = (Integer.parseInt(jTxtNominaLaboral.getText()));

    jTxtNominaLaboral.setText("");
    jTxtNominaLaboral.requestFocusInWindow();
    c.inserta_registro();

    //Aqui en esta linea es donde quiero que se haga una pausa a la hora de mostrar el resultado en la caja de texto y despues que la limpie
    jTxterrorLaboral.setText(String.valueOf(c.persona));

    try {
    Thread.sleep(2000);

    } catch (InterruptedException ie) {
    System.out.println(ie.getMessage());
    }
    jTxterrorLaboral.setText("");

    } catch (Exception ex) {
    ex.printStackTrace();
    }
    }
    }
    }


    No tengo ni la menor idea de como hacerle para que la pausa la haga despues, ya le movi ya le hice y deshice pero nada!!!!

  1. Alberto dijo...:

    Muy buen hilo. Gracias ..... Si hubiera tenido una escopeta a mano me hubiera cargado al maldito pájaro, es bastante coñazo

    Un saludo

  1. José Cáceres dijo...:

    Jajajaj totalmente de acuerdo con Alberto, ese pajarraco azul molesta y bastante, en fin, muchas gracias, he estado leyendo tus demás posts acerca de hilos y me han servido mucho.

  1. Antonela dijo...:

    Muchas gracias! Fue de mucha ayuda

  1. Jav dijo...:

    MUY BIEN EXPLICADO... MUCHAS GRACIAS, ME SACASTE DE MUCHAS DUDAS... EXITO!

Publicar un comentario

Este es un espacio abierto, puedes escribir lo que gustes respetando los siguientes puntos:

1.- Lo que escribas esté relacionado con el post, si gustas contactarme puedes hacerlo aqui.

2.- Todo es cuestionable, aunque ten en cuenta que existen formas de hacerlo, evita las agresiones y revisa tu lenguaje antes de publicar un comentario.

3.- Siempre hay tres verdades: tu verdad, mi verdad y la verdad, por lo que opiniones diferentes no necesariamente son equivocadas.

4.- Los comentarios son una forma de discusión abierta, por lo que al publicar uno, implícitamente entras a una discusión, con todo lo que esto representa.

5. Me reservo el derecho de eliminar comentarios que no respeten las condiciones mencionadas anteriormente.

Toma en cuenta que puedes utilizar emoticones en tu comentario, para ver una lista de los disponibles da clic en este enlace.

 
Monillo007 © 2010 | Designed by Trucks, Manual Bookmarking | Elegant Themes