Simulación 1
Para crear una clase que define una Hebra o un Hilo en Java se puede extender la clase Thread.
En este ejemplo, se esta creando una clase llamada "Demonio1" que especificará el comportamiento de una hebra. Gráficamente sería:
Toda hebra define sus acciones en un método que tiene que llamarse "run( )".
Así pues, si quisiéramos que nuestra hebra imprima el mensaje "Hola mundo" 5 veces. Entonces dentro del método "run( )" de la clase que define la hebra, se debe crear un ciclo que imprimirá el mensaje por 5 veces, así:
Gráficamente, podemos observar que ya se implemento el método "run( )" que define nuestro requerimiento. Nuestro requerimiento es bastante simple:"imprimir un mensaje 5 veces".
Para probar nuestra hebra en ejecución, debemos instanciarla. Para esto podemos crear una nueva clase para nuestra primera simulación, la llamaremos "Simulacion1".
Esta nueva clase "Simulación1", sólo es para crear un escenario donde podamos probar nuestra hebra. En esta clase, si se debe implementar el método "main( )" que permitirá realizar nuestra simulación.
Por eso se crea un nuevo objeto "d1" que es la instanciación de nuestra hebra "Demonio1" en ejecución. Recordemos que nuestras clases entran en ejecución cuando se instáncian. Esta vez con "new".
Al ejecutar "Simulacion1.java", es decir hacer una primera simulación (Debug As -> Java Application), se obtiene la impresión de un mensaje por 5 veces:
También puedes crear un archivo JAR "Simulación1.jar", para probar tu simulación desde la consola de tu sistema operativo.
Simulación 2
Podemos plantear otra simulación, sencillamente creando una hebra más, que también haga lo mismo. Imprimir el mensaje "Hola Mundo" también. Para esto no necesitamos crear otra clase que extienda Thread, simplemente instanciando otra vez la hebra "Demonio1" con un nuevo objeto, que llamaremos "d2".
Al ejecutar "Simulación2.java", se obtiene 10 mensajes en consola. Cinco son de la hebra "d1" y los otros cinco de la hebra "d2".
Por supuesto en la impresión de los mensajes, no se puede diferenciar, cual de los mensajes le corresponde a una determinada hebra.
Simulación 3
Para poder identificar una hebra, se podría crear el atributo "String nombre" y personalizarla en el constructor de la clase que defina la hebra. Este atributo sería de tipo cadena y podría imprimirse en cada mensaje y así saber de que hebra se trata. Ver "Demonio2.java"
También necesitamos personalizar nuestra nueva simulación. Ver "Simulacion3.java"
Hasta ahora tenemos gráficamente lo siguiente:
La clase "Demonio2", define el mismo comportamiento de la clase "Demonio1". Salvo que en "Demonio2" se define el atributo nombre que se especifica en un constructor.
El ejecutar "Simulacion3.java" se debería obtener, impresión de mensajes con identificación. Se muestran 4 ejecuciones diferentes y se aprecia que un hilo es inesperado ya que no se puede precisar con exactitud cual de las hebras se ejecuta en un instante de tiempo, simplemente se ejecutan y el sistema operativo es el encargado de administrar los recursos.
También podemos ejecutar el archivo "Simulacion3.jar" desde consola del sistema operativo.
Simulación 4
En muchas situaciones, no se precisa el numero de veces que se desea ejecutar algunas sentencias en una hebra. Para eso se deben utilizar bucles infinitos. Ver "Demonio3.java"
En la clase "Demonio3" se define una hebra que imprimirá un mensaje y después habrá un retardo de 2 segundos (2000 mili segundos). Este retraso de 2 segundos se consigue con la función "sleep( )", propia de las hebras. Es decir dormir por una cantidad determinada de mili segundos.
La línea 16 es muy peligrosa porque maneja excepciones, así que esto lo soluciona automáticamente el eclipse. Haciendo clic a la línea del error y seleccionando "Surround with try/catch", de tal manera que queda así:
La clase "Demonio3" ya no utiliza un atributo nombre para identificarse. Por medio de su constructor personaliza el nombre a la superclase "Thread". Por consiguiente la clase "Thread" recibe un "String" en uno de sus constructores y devuelve el nombre personalizado con el método "getName( )"
En este nuevo escenario de simulación(Ver "Simulacion4.java"), se imprimen mensajes hasta el infinito y para detener la ejecución, usted debe hacer clic en el botón terminar "Terminate"
Para detener la ejecución desde consola del sistema operativo use la combinación de teclas "Control+C"
Simulación 5
Para una última simulación usaremos GUI(Interfaz gráfica de usuario), que hace mucho más atractiva la simulación.
Crearemos una interfaz gráfica haciendo clic en el paquete del proyecto y seleccionando "New"->"Other..."
Luego seleccionaremos "Application Window" ubicado en "Window Builder"->"Swing Designer"->"Application Window" con nombre "Simulacion5", así:
Al hacer clic en "Finish" se generara código fuente para generar una ventana básica. En esté código podemos identificar 3 partes:
1. La Función principal "main( )", que se ejecuta al inicio de la aplicación.
2. El constructor de la clase "Simulacion5( )", que se ejecuta al crearse la ventana. Hace una llamada a la función "initialize( )"
3. Y finalmente la función "initialize( )", que inicializa los controles, componentes, propiedades de una interfaz gráfica.
Se trata del tipo de interfaz gráfica "JFrame".
Al hacer clic en la pestaña "Design", se generara un ambiente para diseñar de manera gráfica.
Primero: Agregar el Layout "GroupLayout" a la ventana.
Segundo: Agregar el Container "JScrollPane" dentro del Layout ingresado anteriormente. Este Container manejará, nuestro futuro JTextArea.
Tercero: Agregar el Componente "JTextArea", dentro del scrollPane().
Nota: Tener cuidado de que cada elemento este contenido dentro de su correspondiente contenedor.
Cuarto: Agregar un botón para Iniciar/Detener la simulación. Este botón sin embargo esta en "getContentPane( )". También vamos a crear otro botón "Terminar" y una etiqueta para el CopyRight.
Se harán uso de los métodos propios de todo Thread en Java.
El método start(): Para poner en marcha este nuevo Thread se debe llamar al método start(), heredado de la súper-clase Thread. El método start() es el que crea al Thread y en algún punto hace que ese Thread ejecute lo que esta en run().
El método sleep(): El método sleep() simplemente le dice al Thread que duerma durante los milisegundos específicos. Se debería utilizar sleep() cuando se pretenda retrasar la ejecución del Thread, sleep() no consume recursos del sistema mientras el Thread duerme. De esta forma otros Threads seguir funcionando.
objThread.sleep(1000) //Duerme al hilo objThread 1 seg
El método suspend(): –Deprecado(No se debe utilizar) – Puede resultar útil suspender la ejecución de un Thread sin marcar un límite de tiempo. Si, por ejemplo, esta construyendo un applet con un Thread de animación, querrá permitir al usuario la opción de detener la animación hasta que quiera continuar. No se trata de terminar la animación, sino desactivarla. Para este tipo de control de Thread se puede utilizar el método suspend(). objThread.suspend();
El método resume(): –Deprecado(No se debe utilizar) – El método suspend() no detiene la ejecución permanente. El Thread queda suspendido indefinidamente y para volver a activarlo de nuevo necesitamos realizar una invocación al método resume();
objThread.resume();
La ejecución de la Simulación se muestra a continuación: