Hilos

1. En la clase Ej1se crean hilos utilizando la interfaz Runnable. De esta forma podremos crear múltiples hilos que ejecuten el mismo método run() de esta clase accediendo al mismo espacio de memoria de este objeto. Ejecutar el programa, ver lo que hace, consultar el código fuente y contestar a las siguientes preguntas:

a) Explica que es lo que hace la condición de terminación del bucle while en el método run(). ¿Qué utilidad le ves?

b) ¿Puede haber en algún momento dos hilos ejecutando simultáneamente el método run()?

c) ¿Si hubiese dos hilos ejecutando el run(), podría haber conflictos en el acceso a la variable ini? Es decir, que un hilo sobrescriba el valor que había escrito en ella el otro hilo ¿Por qué?

d) ¿Cómo podemos parar este hilo sin crear uno nuevo?

2. En la clase Ej2 tenemos un programa que muestre una carrera entre tres hilos de distintas prioridades. Se pide:

a) Cada hilo tiene su propio contador que se va incrementando cada iteración de dicho hilo. En este caso, ¿podrá haber conflicto en el acceso al contador del hilo entre los distintos hilos? ¿Por qué?

b) Fíjate en el bucle principal en el que se imprime el contador de cada hilo, ¿cuál es su condición de terminación?

c) En cada iteración los hilos hacen una operación costosa. En este caso estamos forzando a que llamen al colector de basura (garbage collector) con la instrucción System.gc(). Sustituir esta instrucción por dormir durante 100ms y probar. ¿Qué ocurre en este caso? ¿Por qué? Volver a dejar el programa como antes, con la llamada al colector de basura.

d) En el método run() de Hilo, añade la instrucción necesaria para que en el caso de que el hilo t sea distinto de null se quede bloqueado hasta que dicho hilo termine su ejecución. Probar el programa y ver lo que ocurre en este caso.

e) Prueba cambiando las prioridades de los hilos. Cuando tenemos hilos de alta prioridad e hilos de baja prioridad, cuando los de alta prioridad terminan, ¿qué ocurre con los de baja prioridad? ¿por qué?

3. En este ejercicio vamos a resolver el problema de los productores y los consumidores. Vamos a definir 3 clases: el hilo Productor, el hilo Consumidor, y el objeto Recipiente donde el productor deposita el valor producido, y de donde el consumidor extrae los datos.

El programa mostrará cuando el productor produce un valor y cuando el consumidor lo consume. El funcionamiento correcto debería ser que el consumidor consuma exactamente los mismos valores que el productor ha producido, sin saltarse ninguno ni repetirlos. Se pide:

a) Compilar y probar el programa. ¿Funciona correctamente? ¿Por qué? Ejecutar varias veces y explicar lo que pasa. ¿Qué tendremos que hacer para que funcione correctamente?

b) Vamos a añadir el código necesario en los métodos produce y consume para sincronizar el acceso a ellos. El comportamiento debería ser el siguiente:

¿Qué métodos utilizaremos para la sincronización? Insertar el código necesario y compilar. Probar el programa, ¿da alguna excepción? En caso afirmativo, ¿por qué? ¿será necesario añadir algo más en el encabezado de los métodos produce y consume? Hacer las modificaciones necesarias.

Compilar y comprobar que el programa funciona correctamente.