La segunda forma de crear instancias concurrentes, es implementando la interface Runnable.
Esta interface, nos obliga a implementar el método run () igual que antes, con lo que luego podremos utilizar la clase Thread para lanzar la ejecución
Vamos a escribir una clase que escriba 100 veces un mensaje, y como queremos que corra como un hilo, daremos las órdenes en el método run (). Veremos que es idéntica a la anterior, pero en lugar de extender Thread, implementa Runnable
Notas:
Línea 3 – Debemos implementar la interface Runnable
Líneas 5 a 9 – Definimos una variable privada en donde podremos dejar un mensaje, y proporcionamos un método setter para cargarla
Líneas 12 a 21 – Establecen todo el flujo del programa; equivalen al método main que estábamos utilizando hasta ahora, y que era el que realizaba las funcionalidades del programa.
- Se trata de un bucle para que escriba 100 veces un mensaje (línea 14), pero después de cada impresión, provocamos una parada de 1 segundo
A continuación escribimos una clase sencilla que instancie esta clase un par de veces, le cargue mensajes distintos y llame al método run(). (Aparece marcado las líneas distintas alejemplo anterior)
Notas:
Líneas 6 y 7 – Creamos dos instancias de la clase Mensaje
Líneas 9 y 10-Cargamos cada instancia con un mensaje distinto
Líneas 12 y 13-Creamos instancias de Thread para cada instancia que deseemos lanzar
Lineas 15 y 16- Damos orden de inicio de ejecución. Internamente, se llamara al método run()
A partir de ese momento, las dos instancias se ejecutaran a la vez, imprimiendo y esperando un segundo. Como la consola es un recurso único, las clases se alternaran a escribir en la misma. La alternancia no tiene que ser perfecta, porque quien va dando tiempo a cada hilo es el S.O., pero la salida será algo como esto:
Runnable vs Thread
Tras ver la poca diferencia que existe en programación en la utilización de cualquiera de los dos métodos, ¿Cuál debemos escoger?
Se aconseja implementar Runnable, ya que aporta algunas ventajas
- No rompe nuestra línea de herencia. Podemos heredar de donde nos convenga, e implementar Runnable
- La clase sigue siendo “normal”, solo hay un método que hace el trabajo con un nombre concreto
- Si queremos abandonar los hilos, solo tenemos que seguir llamando a la clase, pero en lugar de utilizar start(), utilizamos run(), y nuestra clase se quedara detenida hasta que la otra termine el trabajo
Gestión de hilos (Threads)
El S.O. se encarga de asignar los tiempos de trabajo a cada hilo.
- Se produce un cambio de hilo:
- Cuando se le acaba el tiempo asignado
- Cuando se produce una interrupción (entrada/salida, evento,…)
- Si todos los hilos tienen la misma prioridad, todos se ejecutaran en algún momento
- Si hay hilos con mayor prioridad pendientes, no se tienen porque ejecutar los de menor prioridad
Las prioridades se pueden ajustar desde programación
- setPriority(int) Establece prioridad del hilo
- getPriority() devuelve la prioridad del hilo
- Constantes disponibles
- MAX_PRIORITY (=10): prioridad máxima
- MIN_PRIORITY (=1): prioridad mínima
- NORM_PRIORITY (=5): prioridad por defecto.
Todo hilo puede ser interrumpido, con el método interrupt()
Para ello, el hilo debería estar comprobando si le llega la petición
Otros Métodos:
- void start(): usado para iniciar thread. Hace que se ejecute el código contenido en run()
- void sleep(): pone a dormir una thread por un tiempo mínimo especificado.
- void join(): esperar el final de la thread sobre la cual el método es invocado,
- void yield(): Mueve a la thread desde el estado de corriendo al final de la cola de procesos en espera por la CPU
- boolean isAlive(): Comprueba si un hilo está activo
- void setName(String name):Le asigna un nombre al hilo
- static Thread currentThread(): devuelve la referencia al Thread que ha llamado a este método