Programación III (Java) - 08 threads

5,857 views
5,638 views

Published on

Published in: Education
0 Comments
8 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
5,857
On SlideShare
0
From Embeds
0
Number of Embeds
0
Actions
Shares
0
Downloads
0
Comments
0
Likes
8
Embeds 0
No embeds

No notes for slide

Programación III (Java) - 08 threads

  1. 1. 8. Threads (hilos) ¿Qué es un thread? Funcionamiento básico Clase java.lang.Thread Mecanismos de manipulación de threads Ciclo de vida de un thread Métodos sincronizadosProgramación III Tema 8 - Threads
  2. 2. ¿Qué es un thread? • Programación Tradicional – Un procesador → Un flujo de control – Flujo de Control = Flujo de Ejecución = Hilo de Ejecución • Programación multihilo (multithread) – Permite la ocurrencia simultánea de varios flujos de control • Aun cuando siga existiendo un solo procesador – Cada uno de ellos puede programarse independientemente • O no. Puede compartir parte o todo el código con otros – Pueden realizar un trabajo distinto, idéntico o complementario • Un Thread es un hilo de ejecución que... – se ejecuta en paralelo e “independiente” de otros hilos – puede trabajar sobre datos propios o datos compartidos, – puede en un momento dado pararse, reiniciarse, sincronizarse o esperar a otros hilos.Programación III Tema 8 - Threads
  3. 3. Un hilo NO ES un código • Sino quien ejecuta secuencialmente ese código Hilo Hilo Hilo Hilo principa thread1 thread2 swing l main (...) { run() { ... ... obj.m1(); o.m1(); ... ... } } mouseClicked() { ... test.m1(); m1 (...) { ... ... } ... }Programación III Tema 8 - Threads
  4. 4. Un hilo NO ES su(s) recurso(s) • (recursos, datos, objetos...) hilo 1 hazTortilla() { hilo 2 ... miC = new Cocina(); miC.cogeHuevos(); miC.cogeSarten(); miC.ponFuego(); ... } hilo == persona ("ejecuta") programa == acciones ("receta") datos == objetos ("ingredientes")Programación III Tema 8 - Threads
  5. 5. Pero ojo con los recursos compartidos... • Posible lío!!! (luego lo vemos) hilo 1 hilo 2 hazTortilla() { ... miC = laUnicaCocina(); miC.cogeHuevos(); miC.cogeSarten(); miC.ponFuego(); ... }Programación III Tema 8 - Threads
  6. 6. Funcionamiento básico (1/2) • Además entonces del hilo principal y del hilo de swing... – podemos crear otros hilos independientes – que se ejecutan en paralelo al código de los demás hilos. • Pero... ¿qué código ejecutan los threads? – Los threads ejecutan el código que se encuentra dentro algún método run()... • bien del propio thread, • bien de otro objeto.Programación III Tema 8 - Threads
  7. 7. Funcionamiento básico (2/2) • Método run() del propio Thread – Todo thread posee un método run() que por defecto es el código que se ejecuta cuando se pone en marcha el Thread • Este método por defecto se encuentra vacío  sobreescribir • Método run() de otros objetos – El método run() no es exclusivo de los threads – Otros objetos pueden implementar este método • Interfaz Runnable – Así, un thread también puede ejecutar (como un hilo de ejecución independiente) el método run() de otros objetosProgramación III Tema 8 - Threads
  8. 8. Clase java.lang.Thread (1/3) • En Java, para trabajar con Threads se utiliza la clase Thread, del paquete java.lang. • Constructores: – Thread( ) • Crea un thread con nombre "Thread-"+n – Thread( String name ) • Crea un thread con el nombre indicado como parámetro. – Thread( Runnable target ) • Crea un thread asociado al objeto destino. – Combinaciones – Uso de grupos de threadsProgramación III Tema 8 - Threads
  9. 9. Clase java.lang.Thread (2/3) • Algunos métodos: – static Thread currentThread() • Devuelve el thread en curso – String getName() – void setName(String name) – int getPriority() – void setPriority(int newPriority) • Asigna prioridades relativas – ThreadGroup getThreadGroup() – void run()Programación III Tema 8 - Threads
  10. 10. Clase java.lang.Thread (3/3) • Creación y Puesta en marcha de Threads: – Los Threads, como todo en Java, son objetos – Java necesita saber que se “lanza” un nuevo hilo Para eso se ejecuta el método start() – Por ejemplo: Thread miThread = new Thread(); MiThread.start(); – Así, tenemos un thread que no hace nada, cuando se invoca el método start() no se ejecuta ningún código porque por defecto el método run() de un thread está vacío.Programación III Tema 8 - Threads
  11. 11. Creando threads (1/4) • Existen dos mecanismos para trabajar con Threads: – Heredar de la clase Thread – Implementar el interface Runnable • 1. Heredando de la clase Thread – Se hereda de la clase Thread y se sobrescribe el método run() Ejemplo: ThreadHeredando.javaProgramación III Tema 8 - Threads
  12. 12. Creando threads (2/4) • Salida obtenida: Final del main 1111111111111111111111111111111222222222222 2222222222222222222222122111111112211222111 1111111111111111111111111222222222222222222 2211122222222222211111111111111111111111111 1222222222222222222222222222 • ¿Por qué el desorden? Cada salida puede diferir – Una vez lanzados, no sabemos cuál será el tiempo de ejecución de los hilos • ¿Cuántos hilos de ejecución existen en este ejemplo?  3 – El hilo de ejecución del thread t1 – El hilo de ejecución del thread t2 – El hilo de ejecución del mainProgramación III Tema 8 - Threads
  13. 13. Creando threads (3/4) • 2. Implementando el interfaz Runnable – El interface Runnable (java.lang.Runnable) sólo tiene un método: public interface Runnable { void run(); } – Procedimiento: • Crear una clase que implemente el interface Runnable • Crear un objeto de esa clase • Vincular ese objeto a un thread – Resultado: • Al poner en marcha el thread, éste ejecutará el código que el objeto posea en su método run()Programación III Tema 8 - Threads
  14. 14. Creando threads (4/4) • Por ejemplo: Class MiRunnable implements Runnable { void run() { // haz algo } public static void main( String[] args ) { Runnable objeto = new MiRunnable(); Thread hilo = new Thread( objeto ); hilo.start(); } • hilo.start() -> objeto.run()Programación III Tema 8 - Threads
  15. 15. Esperando a que un hilo acabe (1) • Otro ejemplo (HiloEjemploRunnable.java): class HiloEjemplo implements Runnable { static long horaInicio = System.currentTimeMillis(); int cont = 0; int num; HiloEjemplo( int numObjeto ) { num = numObjeto; } public void run() { while( System.currentTimeMillis()-horaInicio < 3000) { System.out.print( num ); cont++; } } public void visualizar() { System.out.println( "Objeto num. " + num + " - " + cont + " veces." ); } }Programación III Tema 8 - Threads
  16. 16. Esperando a que un hilo acabe (2) • Posible main(): Thread[] t = new Thread [4]; HiloEjemplo[] o = new HiloEjemplo[4]; for (int i = 0; i < 4; i++) { o[i] = new HiloEjemplo(i); t[i] = new Thread(o[i], "Objeto-" + i); System.out.println( "nuevo Thread() " + (t[i]==null?"fallo":"correcto")+" - "+t[i].getName() ); } for (int i = 0; i < 4; i++) t[i].start(); try { for (int i = 0; i < 4; i++) t[i].join(); } catch (InterruptedException e) { } for (int i = 0; i < 4; i++) o[i].visualizar(); • El hilo que hace el join espera a que el hilo de ese objeto finaliceProgramación III Tema 8 - Threads
  17. 17. Esperando a que un hilo acabe (3) • Salida obtenida: nuevo Thread() correcto - Objeto-0 nuevo Thread() correcto - Objeto-1 nuevo Thread() correcto - Objeto-2 nuevo Thread() correcto - Objeto-3 0000000000000000000000000000000000000000011111111 1120312033333333312000000000031111111111203120311 1111111203111111111111122222222222000002333111111 1 (…) 2331111111112301233301230111111111111111122222333 3012222222222223000000111111111111111111111222222 222222222222222223000000000031203 Objeto num. 0 - 297 veces. Objeto num. 1 - 341 veces. Objeto num. 2 - 213 veces.Programación III Objeto num. 3 - 302 veces. Tema 8 - Threads
  18. 18. Ciclo de vida de un thread (1) Bloqueado Esperando Esperando-tiempo • getState()  Thread.State – NEW – RUNNABLE – BLOCKED, WAITING, TIMED_WAITING – TERMINATEDProgramación III Tema 8 - Threads
  19. 19. Ciclo de vida de un thread (2) • Estado TIMED_WAITING: – Método sleep() • Método de clase (static) que permite dejar dormido (not runnable ) al thread en curso durante un determinado tiempo – En este estado el thread no consume recursos  no es candidato a ser elegido por el dispatcher para su ejecución ... Thread.sleep(1000); ... • El thread que estaba ejecutando ese código (thread en curso) se duerme durante 1 segundo  el código no continua ejecutándose hasta al menos 1 segundo • La temporización no es exacta!Programación III Tema 8 - Threads
  20. 20. Interrupción de hilos • sleep puede lanzar InterruptedException • Eso ocurre si algún otro hilo le interrumpe: – Método Thread.interrupt() en el objeto a ser interrumpido – Fuera del sleep, la interrupción debe ser gestionada por el programador en el run(): public void run() { while(System.currentTimeMillis()-horaInicio<3000) { System.out.print( num ); cont++; if (Thread.interrupted()) break; } }Programación III Tema 8 - Threads
  21. 21. Sincronización de hilos (1) • Programar en varios hilos tiene muchas ventajas pero algunos peligros – ¿Y si varios acceden al mismo dato? – ¿Y si varios ejecutan el mismo método? • (EjemploProblemasSincronizacion.java) • ¿Cómo solucionamos estos problemas? esp[183452].fecundaOvulo(ov) yo.veAlBaño(unicoBaño)Programación III Tema 8 - Threads
  22. 22. Sincronización de hilos (2) • Modificador synchronized • Puede aplicarse sobre: – Un método de instancia • En cada momento sólo habrá un hilo ejecutando un método sincronizado sobre cada objeto – Un método de clase • En cada momento sólo puede haber un thread ejecutando un método sincronizado sobre la clase o cualquier objeto de la clase – Un objeto tal cual - synchronized(obj) • Bloquea a los que no pueden "entrar" • (EjemploProblemasSincronizacion2.java)Programación III Tema 8 - Threads
  23. 23. Sincronización de hilos (3) • Entonces ¿mejor sincronizamos todos los métodos? – No. Es menos eficiente (tiempo de ejecución) – Y puede dar lugar a interbloqueos (un gran peligro de la programación multihilo) • (EjemploProblemasInterbloqueos.java) • Sincronicemos con prudencia – Evitando interbloqueosProgramación III Tema 8 - Threads
  24. 24. Sincronización de hilos (4) • Estado WAITING: – Método objeto.wait() • Causa que el thread en curso se quede esperando – Ligado a un objeto • Hasta que otro thread “libere” – A ese mismo objeto • Métodos para liberar – objeto.notify() » Libera uno de los que esté esperando – objeto.notifyAll() » Libera a todos los que estén esperandoProgramación III Tema 8 - Threads
  25. 25. En resumen... • Ciclo de vida de un thread: – NEW - tras la construcción – RUNNABLE - tras start() • BLOCKED – Esperando a entrar en un synchronized (hasta que otro salga) • WAITING – wait (esperando a un notify()) – join (esperando a que termine otro/s) • TIMED_WAITING – sleep (esperando un tiempo) » También wait o join con timeout – TERMINATED - al acabar el run()Programación III Tema 8 - Threads
  26. 26. Swing • No es “thread-safe” – Lo seguro es que sólo él acceda a todos los elementos visuales (ventanas y componentes en ventanas) • Cuidado con las llamadas a Swing desde fuera de los eventos • Hay tres tipos de threads para swing: – El thread inicial (el main) – El hilo de gestión de eventos (event dispatcher) – Hilos de trabajo (worker threads), si procedeProgramación III Tema 8 - Threads
  27. 27. Hilo inicial • Es el del programa (main). Incluso la creación de ventanas puede hacerse de un modo seguro: – SwingUtilities.invokeLater( Runnable ) – "hazlo cuando puedas" public static void main(String[] args) { SwingUtilities.invokeLater( new Runnable() { public void run() { createAndShowGUI(); } }); }Programación III Tema 8 - Threads
  28. 28. Hilo de gestión de eventos • Es el hilo principal de swing – Todos los componentes de Swing (excepto los explícitamente "thread-safe" que son unos pocos) deben ser llamados desde este hilo • Deberían ser tareas pequeñas • Deberían acabar rápido • Si no es así, la gestión de eventos se congela y el IU no responde – Para tareas largas hacer la gestión desde fuera del hilo • Cuando se necesite acceder a un componente Swing, invokeLater • Si no se supiera si estamos o no en ese hilo: – javax.swing.SwingUtilities.isEventDispatchThread()Programación III Tema 8 - Threads
  29. 29. Hilos trabajadores – Para integrarse con Swing se pueden usar threads normales que invoquen runnables de Swing cuando lo necesiten • Pero también pueden usarse worker threads – Es una plantilla predefinida de hilo que interactúa con Swing: • doInBackground() como un run() que devuelve result – Puede llamar a publish( valor ) • process( cola ) recoge la cola de publish – LO LLAMA EL HILO DE GESTION DE EVENTOS • done() se hace al finalProgramación III – LO LLAMA EL HILO Tema 8 GESTION DE EVENTOS DE - Threads
  30. 30. Resumen: consejos Swing/hilos • Sólo utilizar componentes Swing desde el hilo de Swing salvo métodos thread-safe – En particular, los consultores son siempre más seguros que los modificadores – invokeLater( r ) – invokeAndWait( r ) // síncrono • Código de los gestores de eventos: breve • Crear otro hilo desde el gestor si hace falta un código largo – A "mano" o usando SwingWorkerProgramación III Tema 8 - Threads

×