Programación concurrente
3.1 Concepto de hilo.
¿Qué son los hilos?
Un thread es básicamente una sección de código independiente que el procesador puede ejecutar
de forma concurrente junto a otros threads o hilos de ejecución. En Linux y otros UNIX un thread se
define como un contexto de ejecución mientras que Windows define un thread como algo separado
de un proceso.
Siempre que ejecutamos una aplicación, se crea un thread llamado el main thread, desde él, se
pueden crear nuevos threads que ejecuten otras partes del código de nuestra aplicación en
paralelo o que escuchen en un socket o cualquier otra cosa que se nos ocurra y necesitemos.
Los threads deben interactuar entre si, por lo tanto es necesario implementar mecanismos
de comunicación y sincronización pues la memoria de los mismos se comparte entre todos ellos por
igual y todos ellos tienen acceso al mismo segmento de memoria en cualquier momento por lo que
la integridad de los datos puede verse comprometida si no usamos primitivas de sincronización.
En el contexto de un Programa concurrente, un Hilo (Thread) es cada uno de los flujos secuenciales
de control independientes especificados en el programa.
Un hilo o thread es cada una de las tareas que puede realizar de forma simultánea una aplicación.
Por defecto, toda aplicación dispone de un único hilo de ejecución, al que se conoce como hilo
principal. Si dicha aplicación no despliega ningún otro hilo, sólo será capaz de ejecutar una tarea al
mismo tiempo en ese hilo principal.
Así, para cada tarea adicional que se quiera ejecutar en esa aplicación, se deberá lanzar un nuevo
hilo o thread. Para ello, todos los lenguajes de programación, como Java, disponen de una API para
crear y trabajar con ellos.
En cualquier caso, es muy importante conocer los estados en los que se pueden encontrar un hilo.
1 - Estados de un hilo
Actividad Diferencia entre proceso e hilo
realizar un cuadro comparativo que inculya su criterio.
3.2 Comparación de un programa de flujo único contra uno de flujo
múltiple.
Actividad
cuadro comparativo entre programa de flujo unico contra flujo múltiple
3.3 Creación y control de hilos.
Creación y ejecución de un hilo
Para la creación de hilos en Java disponemos de varias vías, combinando el uso de la clase Thread y
el interface Runnable según nos interese:
• Podemos utiliza la clase Thread heredando de ella. Es quizás la forma más cómoda porque
una clase que hereda de Thread se convierte automáticamente en un hilo. Tiene una pega:
esa clase ya no podrá heredera de ninguna otra, por lo que si la arquitectura de nuestra
aplicación lo requiere ya no podríamos.
• Si tenemos la limitación que acabamos de comentar para el primer caso, podemos
implementar el interface Runnable de forma que la clase que nosotros estamos
implementado podrá además heredar sin ninguna limitación. Sólo cambia un poco la forma
de trabajar directamente con la clase hilo.
• Por otra parte también podemos crear un hilo utilizando una clase anónima. No es un
método que se recomiende pero en algunos casos, cuando la clase que hace de hilo no va a
tener una estructura concreta es bastante cómodo hacerlo de esta manera.
Crear un hilo heredando de la clase Thread
En este caso, la clase Tarea se conviene automáticamente en un hilo por el mero hecho de heredar
de Thread. Sólo tenemos que tener en cuenta que, al heredar de esta clase, tenemos que
implementar el método run() y escribir en él el código que queremos que esta clase ejecute cuando
se lance como un hilo con el método start() (que también hereda de Thread)
Crear un hilo implementado el interfaz Runnable
En este caso, suponemos que necesitamos que nuestra clase hilo herede de una segunda clase. En
este caso, la clase deberá además implementar el interfaz Runnable y, como en el primer caso,
implementar el método run() con la misma idea que en el punto anterior. Más adelante, tendremos
que crear un objeto directamente de la clase Thread y pasarle como parámetro al constructor un
objeto de nuestra clase hilo. De esa manera, el objeto Thread será un hilo que se comportará como
el método run() de nuestra clase Tarea haya definido.
En cualquier caso tenemos que tener siempre en cuenta las siguientes consideraciones:
• Siempre se debe sobreescribir (Override) el método run() e implementar allí lo que tiene que
hacer el hilo
• Podemos hacer que el hilo haga un número finito de cosas o bien que esté siempre en
segundo plano (tendremos que asegurar que el método run() se ejecuta de forma
continuada)
• Los problemas vienen cuando existen varios hilos. Hay que tener en cuenta que pueden
compartir datos y código y encontrarse en diferentes estados de ejecución
• La ejecución de nuestra aplicación será thread-safe si se puede garantizar una correcta
manipulación de los datos que comparten los hilos de la aplicación sin resultados
inesperados
Práctica 1:
Realizar la creación de hilos (implementar los ejemplos mostrados).
Práctica 2:
Realizar un programa para una animación en la cual utilice hilos dibujando varias partes de la
pantalla
Nota(con el desarrollo de esta práctica más la práctica uno se excenta el examen.)
3.4 Sincronización de hilos computación.
Sincronización de hilos
El API de Java proporciona una serie de métodos en la clase Thread para la sincronización de los hilos
en una aplicación:
• join() Se espera la terminación del hilo que invoca a este método antes de continuar
• [Link](int) El hilo que ejecuta esta llamada permanece dormido durante el tiempo
especificado como parámetro (en ms)
• isAlive() Comprueba si el hilo permanece activo todavía (no ha terminado su ejecución)
• yield() Sugiere al scheduler que sea otro hilo el que se ejecute (no se asegura)
2 - Práctica
Ejecute el código anterior y explique que sucede al aplicar el método.
práctica 2
Práctica aplicar uno de los métodos a alguna de las prácticas anteriores
Examen tema