Está en la página 1de 44

EI1024

MT1024
Programación
Concurrente y
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos

Java y Hebras

Creación y Tema 04. Conceptos Básicos de Concurrencia


Arranque

join
en Java
sleep

Thread-safe

Errores Gregorio Quintana ©


Habituales

Hebras Departamento de Ingeniería y Ciencia de Computadores


Depend. y
Hebras Universidad Jaume I
Independ.

Cesión de
CPU
Curso 2020–21

( 1/ 44)
EI1024
MT1024
Programación
Concurrente y Contenido
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos 1 Java y Hebras

Java y Hebras 2 Creación y Arranque de Hebras


Creación y

Espera a que Termine una Hebra con el Método join


Arranque
3
join

sleep
4 Duérmete un Rato con el Método sleep
Thread-safe

Errores
Habituales
5 Código a Prueba de Hebras (thread-safe)
Hebras
Depend. y 6 Errores Habituales Básicos
Hebras
Independ.

Cesión de
7 Hebras Dependientes y Hebras Independientes
CPU

8 Cesión de CPU

( 2/ 44)
EI1024
MT1024
Programación
Concurrente y Bibliografía
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos

Oaks. Capítulo 1 “Introduction to Threads”.


Java y Hebras

Creación y
Oaks. Capítulo 2 “Thread Creation and Management”.
Arranque

join Patrick Niemeyer y Daniel Leuck.


sleep “Learning Java: A Bestselling Hands-On Java Tutorial”.
Thread-safe O’Reilly Media, 2013.
Errores Capítulo 9 “Threads”.
Habituales

Hebras
Depend. y
Herbert Schildt.
Hebras
Independ.
“Java: A Beginner’s Guide, Seventh Edition”.
Cesión de McGraw-Hill Education, 2017.
CPU
Capítulo 11 “Multithreaded Programming”.

( 3/ 44)
EI1024
MT1024
Programación
Concurrente y Un Problema Típico
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos

Se desea evaluar una función muy compleja en múltiples


puntos para representarla gráficamente con gran detalle.
Java y Hebras

Creación y
Arranque Un usuario compra un ordenador con 8 núcleos para
join ejecutar más rápidamente un código en Java que realiza
sleep dicho cálculo.
Thread-safe

Errores 1 for ( i = 0; i < n ; i ++ ) {


Habituales
2 v [ i ] = funcionCompleja ( i ) ;
Hebras
Depend. y 3 }
Hebras
Independ.

Cesión de
CPU
¿Cuántos núcleos trabajan cuando lo ejecuta?

( 4/ 44)
EI1024
MT1024
Programación
Concurrente y Objetivos
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos
Ser capaz de realizar tareas básicas (sin comunicación ni
sincronización) en las que se aprovechen los beneficios de
la concurrencia y el paralelismo.
Java y Hebras

Creación y
Arranque
1 Ser capaz de crear hebras.
join

sleep 2 Ser capaz de distribuir el trabajo entre todas las hebras.


Thread-safe 3 Ser capaz de esperar a que todas las hebras terminen.
Errores

Ejemplo 1: Una interfaz gráfica más interactiva con la


Habituales

Hebras
Depend. y ayuda de varias hebras. −→ Concurrencia.
Hebras
Independ.

Cesión de
Ejemplo 2: Una aplicación multihebra en la que se
CPU emplean varios núcleos/procesadores para evaluar una
función en múltiples puntos. −→ Paralelismo.

( 5/ 44)
EI1024
MT1024
Programación
Concurrente y
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos

Java y Hebras

Creación y
Arranque

join

sleep

Thread-safe
Java y Hebras
Errores
Habituales

Hebras
Depend. y
Hebras
Independ.

Cesión de
CPU

( 6/ 44)
EI1024
MT1024
Programación
Concurrente y Java y Hebras
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos
Java es un lenguaje diseñado para la concurrencia desde el
principio. No es un añadido a posteriori como en otros
Java y Hebras
lenguajes.
Creación y
Arranque La concurrencia está muy integrada dentro de Java: Todo
join objeto es un monitor (concepto de programación
sleep concurrente).
Thread-safe

Errores Las herramientas básicas de Java para gestionar la


Habituales
concurrencia son:
Hebras
Depend. y 1 Hebras: Tareas.
Hebras
Independ. 2 Monitores: Sincronización.
Cesión de
CPU Las últimas versiones de Java han añadido numerosas
herramientas avanzadas para facilitar la programación
concurrente y paralela: Thread Pools, etc.
( 7/ 44)
EI1024
MT1024
Programación
Concurrente y Java y Hebras (Cont.)
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos
Aunque no se empleen hebras explícitamente, éstas pueden
estar siendo empleadas dentro de la aplicación:
Java y Hebras
AWT y Swing.
Creación y
Arranque
Crean una hebra, llamada hebra event-dispatching, que
join
procesa todos los eventos.
sleep TimerTask.
Thread-safe Permite ejecutar tareas periódicamente.
Servlets y Páginas JavaServer.
Errores
Habituales

Hebras Por cada petición web, se puede crear una hebra.


Depend. y
Hebras RMI.
Independ.
Por cada invocación a un método desde un ordenador
Cesión de
CPU remoto, se puede crear una hebra local para procesarla.
Parallel Streams.
Internamente se usan hebras para aplicar el paralelismo.
( 8/ 44)
EI1024
MT1024
Programación
Concurrente y Java y Hebras (Cont.)
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos
Cuando un usuario ejecuta un programa en Java, el S.O.
crea un proceso.
Java y Hebras Normalmente, este proceso crea a su vez a la hebra
Creación y principal, la cual ejecuta el programa principal.
Arranque

join
Usuario Hebra
sleep Proceso
ejecuta programa principal
Thread-safe

Errores
Habituales

Hebras
Por tanto, el programa principal es ejecutado también por
Depend. y
Hebras
una hebra. Dicha hebra se llama la hebra principal.
Independ.
La hebra principal podría después crear otras hebras.
Cesión de
CPU En este caso, se habla de una aplicación multihebra.
En este caso, todas las hebras están dentro del mismo
proceso.
( 9/ 44)
EI1024
MT1024
Programación
Concurrente y Java y Hebras (Cont.)
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos

Java y Hebras Toda hebra debe tener un cuerpo principal:


Creación y Cuerpo principal de la hebra principal: método main.
Arranque

join
Cuerpo principal del resto de hebras: método run.
sleep
Una hebra termina si se cumple alguna de las siguientes
condiciones:
Thread-safe

Errores
Habituales 1 La hebra alcanza el final de su cuerpo principal.
Hebras
Depend. y
2 Se produce una excepción no contemplada (acceso a un
Hebras elemento fuera de un vector, desbordamiento, etc.).
Independ.

Cesión de
3 etc.
CPU

( 10/ 44)
EI1024
MT1024
Programación
Concurrente y Introducción a la Compartición de Información
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos
La compartición de información es muy útil, pero también
es la principal causa de errores.
Java y Hebras

Creación y
Se abordará en profundidad en los temas siguientes.
Arranque

join Para compartir información correctamente, hay que hacer


sleep algo especial.
Thread-safe Se verá en los temas siguientes.
Errores
Habituales Todas las hebras de una misma aplicación comparten el
Hebras
Depend. y
mismo espacio de memoria.
Hebras
Independ.
No obstante, hay ciertas condiciones:
Cesión de
CPU
1 El montículo es compartido.
2 Las pilas propias de cada hebra no son compartidas.

( 11/ 44)
EI1024
MT1024
Programación Introducción a la Compartición de Información
Concurrente y
Paralela
G. Quintana
(Cont.)
Tema 04.
Conceptos
Información en el montículo:
Básicos Las variables de instancia y las variables de clase
pueden ser compartidas (si se desea), dado que se
Java y Hebras almacenan siempre en el montículo.
Creación y
Arranque Información en la pila:
join
Cada hebra tiene su pila propia, no accesible al resto.
sleep
Por tanto, las variables locales de los métodos no se
Thread-safe
pueden compartir.
Errores
Habituales Nota: Si se declara como variable local una referencia a un
Hebras objeto, la referencia no puede ser compartida. En cambio,
el objeto al que apunta la variable local se crea en el
Depend. y
Hebras
Independ.
montículo, por lo que que sí podría ser compartido.
Cesión de
CPU
1 public void metodo1 ( int a ) {
2 int b = 123;
3 MiObjeto c = new MiObjeto () ;
4 }
( 12/ 44)
EI1024
MT1024
Programación
Concurrente y
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos

Java y Hebras

Creación y
Arranque

join

sleep Creación y Arranque de


Thread-safe

Errores
Habituales
Hebras
Hebras
Depend. y
Hebras
Independ.

Cesión de
CPU

( 13/ 44)
EI1024
MT1024
Programación
Concurrente y Creación y Arranque de Hebras
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos

Java y Hebras Para poder crear hebras útiles, es obligatorio disponer de


Creación y
Arranque
dos cosas: un objeto de la clase (o de una subclase de)
join
Thread y un método run propio.
sleep 1 La clase Thread ofrece el código y estructuras de datos
Thread-safe necesarios para gestionar y guardar la información de una
Errores hebra: espacio para guardar los registros de la CPU,
Habituales
espacio para la pila propia, etc.
Hebras
Depend. y
Hebras
2 El método run será el cuerpo principal de la hebra: el
Independ. código que ejecutará la hebra.
Cesión de
CPU

( 14/ 44)
EI1024
MT1024
Programación
Concurrente y Creación y Arranque de Hebras (Cont.)
Paralela
G. Quintana

Tema 04.
Conceptos
Ejemplo básico: El siguiente código crea una hebra, la cual
Básicos ejecuta su método run.

Java y Hebras 1 /*
Creación y 2 // Clase del sistema . No teclear esta clase .
Arranque 3 class Thread {
join 4 ...
sleep 5 public void run () {
Thread-safe
6 }
7 ...
Errores
Habituales 8 }
Hebras 9 */
Depend. y 10 class EjemploCreacion1 {
Hebras
Independ. 11 public static void main ( String args [] ) {
Cesión de
12 Thread t = new Thread () ;
CPU 13 t . start () ;
14 System . out . println ( " Fin de programa . " ) ;
15 }
16 }
( 15/ 44)
EI1024
MT1024
Programación
Concurrente y Formas de Creación de Hebras
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos

Java y Hebras
El método run de la clase Thread está vacío. Por tanto,
Creación y no ejecuta nada y no hace nada útil.
Arranque

join En consecuencia, necesitamos definir un método run


sleep propio que haga lo que queremos.
Thread-safe

Errores El nuevo método run se puede definir de tres formas:


Habituales

Hebras
1 Dentro de una subclase de la clase Thread.
Depend. y
Hebras 2 Dentro de una clase que implemente la interfaz Runnable.
Independ.

Cesión de 3 Dentro de una clase anónima.


CPU

( 16/ 44)
EI1024
MT1024
Programación
Concurrente y Primera Forma: A partir de una subclase de Thread
Paralela
G. Quintana

Tema 04.
Conceptos Ejemplo: Creación de una hebra como un objeto de una
Básicos
subclase de Thread.
Java y Hebras
1 class MiHebra extends Thread {
Creación y
Arranque 2 public void run () {
join
3 for ( int i = 0; i < 1000; i ++ ) {
4 System . out . println ( " Hola " ) ;
sleep
5 }
Thread-safe
6 }
Errores 7 }
Habituales
8
Hebras
Depend. y 9 class EjemploCreacion2a {
Hebras 10 public static void main ( String args [] ) {
Independ.
11 MiHebra t = new MiHebra () ;
Cesión de
CPU
12 t . start () ;
13 // new MiHebra () . start () ;
14 }
15 }
( 17/ 44)
EI1024
MT1024
Programación
Concurrente y Segunda Forma: A partir de una interfaz Runnable
Paralela
G. Quintana

Tema 04.
Conceptos Ejemplo: Creación de una hebra a partir de un objeto
Básicos
Thread y un objeto con método run:
Java y Hebras
1 class MiRun implements Runnable {
Creación y
Arranque 2 public void run () {
join
3 for ( int i = 0; i < 1000; i ++ ) {
4 System . out . println ( " Hola " ) ;
sleep
5 }
Thread-safe
6 }
Errores 7 }
Habituales
8
Hebras
Depend. y 9 class EjemploCreacion2b {
Hebras 10 public static void main ( String args [] ) {
Independ.
11 Thread t = new Thread ( new MiRun () ) ;
Cesión de
CPU
12 t . start () ;
13 // new Thread ( new MiRun () ) . start () ;
14 }
15 }
( 18/ 44)
EI1024
MT1024
Programación
Concurrente y Tercera Forma: Con clases anónimas
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos
Ejemplo: Creación de una hebra con una clase anónima:
Java y Hebras
1 class EjemploCreacion2c {
Creación y
Arranque 2 public static void main ( String args [] ) {
join 3

sleep
4 Thread t = new Thread () {
5 public void run () {
Thread-safe
6 for ( int i = 0; i < 1000; i ++ ) {
Errores
Habituales
7 System . out . println ( " Hola " ) ;
8 }
Hebras
Depend. y 9 }
Hebras 10 };
Independ.
11 t . start () ;
Cesión de
CPU 12 }
13 }

( 19/ 44)
EI1024
MT1024
Programación
Concurrente y El Arranque es Obligatorio
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos Para poner en marcha una hebra, son obligatorios dos
pasos: Creación y arranque.
Java y Hebras

Creación y
Arranque: El método start pone a la hebra a ejecutar su
Arranque método run, pero no espera a que termine.
join

sleep
Por tanto, el método start es la clave del solapamiento.
Thread-safe Los métodos start y run son dos métodos estándares de
Errores
Habituales
la clase Thread.
Hebras
El método start no se redefine; run, sí se redefine.
Depend. y
Hebras
Independ.
Para ahorrar un paso, dentro del constructor se puede
Cesión de
realizar el arranque con el método start. Así, en la misma
CPU creación ya se arranca la hebra. No recomendable.
Despiste habitual: Olvidar la invocación al método start.
( 20/ 44)
EI1024
MT1024
Programación
Concurrente y Arranque y Solapamiento
Paralela
G. Quintana

Ejemplo de solapamiento entre prog. prin. y dos hebras:


Tema 04.
Conceptos
Básicos

1 public static void main ( String args [] ) {


Java y Hebras 2 ...
Creación y
3 t0 . start () ;
Arranque 4 t1 . start () ;
join 5 pepe () ;
6 ...
sleep
7 }
Thread-safe

Errores
Habituales
main hebra t0 hebra t1
...

Hebras t0.start();
Depend. y
Hebras t1.start();
Independ. pepe();
Concurrencia
...

Cesión de
CPU

En realidad, las hebras no arrancan enseguida. ( 21/ 44)


EI1024
MT1024
Programación
Concurrente y El Método start frente al Método run
Paralela
G. Quintana

Tema 04.
Conceptos ¿Cuál es la diferencia entre que el programa principal
Básicos
ejecute t.run() o ejecute t.start()?
Java y Hebras
public static void main( ... ) { public static void main( ... ) {
Creación y
Arranque
... ...
t.run(); t.start();
join ... ...
} }
sleep

Thread-safe main run de t main run de t


Errores
Habituales

Hebras
Depend. y Concurrencia
Hebras
Independ.

Cesión de
CPU

En el caso de llamar a t.run() es el programa principal (y


no la hebra t) quien ejecuta el código del método run.
( 22/ 44)
EI1024
MT1024
Programación
Concurrente y Paso de Información a las Hebras
Paralela
G. Quintana

Tema 04.
Conceptos El constructor permite pasar información fácilmente a las
Básicos
hebras (antes de que arranquen). Dicha información puede
Java y Hebras
actuar como si fueran parámetros: trabajo a realizar,
Creación y
identificador, etc.
Arranque

join 1 class MiHebra extends Thread {


sleep 2 int miId ;
Thread-safe 3 public MiHebra ( int miId ) {
4 this . miId = miId ;
Errores
Habituales 5 }
Hebras
6 public void run () {
Depend. y 7 System . out . println ( " Soy la hebra : " + miId ) ;
Hebras
Independ.
8 }
9 }
Cesión de
CPU 10 ...
11 MiHebra t = new MiHebra ( 3 ) ;
12 t . start () ;
13 ...
( 23/ 44)
EI1024
MT1024
Programación
Concurrente y
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos

Java y Hebras

Creación y
Arranque

join

sleep
Espera a que Termine una
Thread-safe

Errores
Habituales
Hebra con el Método join
Hebras
Depend. y
Hebras
Independ.

Cesión de
CPU

( 24/ 44)
EI1024
MT1024
Programación Espera a que Termine una Hebra con el Método
Concurrente y
Paralela
G. Quintana
join
Tema 04.
Conceptos El método join detiene a la hebra llamadora hasta que la
Básicos
hebra ha terminado.
Java y Hebras
1 // Crea y arranca la hebra .
Creación y
Arranque
2 MiHebra t = new MiHebra () ;
3 t . start () ;
join
4 // La siguiente sentencia se ejecutar á
sleep
5 // concurrentemente al " run " de la hebra .
Thread-safe 6 ...
Errores 7 // Espera a que la hebra " t " termine .
Habituales
8 t . join () ;
Hebras
Depend. y

El método join debe ser llamado por otra hebra (por


Hebras
Independ.

Cesión de ejemplo, el programa principal).


CPU
Una hebra no puede ejecutar un join sobre sí misma.
Muy útil para la coordinación de hebras.
( 25/ 44)
EI1024
MT1024
Programación
Concurrente y Método join
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos Cuando una hebra o el programa principal realiza la
llamada t.join(), pueden ocurrir dos cosas:
Java y Hebras

Creación y
1 La hebra t ha terminado. ¿Qué ocurre en este caso?
Arranque
2 La hebra t no ha terminado. ¿Qué ocurre en este caso?
join

sleep
Todas las variantes del método join pueden activar la
Thread-safe
excepción InterruptedException.
Errores
Habituales Por ello, es conveniente tratarla:
Hebras
Depend. y 1 try {
Hebras
Independ. 2 t . join () ;
Cesión de 3 } catch ( Interrupt edException ex ) {
CPU 4 ex . printStackTrace () ;
5 }

( 26/ 44)
EI1024
MT1024
Programación
Concurrente y El Método join frente al Método isAlive
Paralela
G. Quintana

Tema 04.
Conceptos El método isAlive() devuelve cierto si una hebra está
Básicos
viva.
Este método no es bloqueante.
Java y Hebras

Creación y
Arranque
Ejemplo: Implementación ineficiente del método join
join sobre una hebra t empleando el método isAlive.
sleep

Thread-safe 1 void myJoin () throws InterruptedException {


Errores 2 // No recomendable ya que conlleva
Habituales
3 // espera activa y tampoco cede la CPU .
Hebras 4 while ( this . isAlive () ) {
Depend. y
Hebras 5 ;
Independ. 6 }
Cesión de 7 }
CPU
8 ...
9 t . myJoin () ;
10 ...
( 27/ 44)
EI1024
MT1024
Programación
Concurrente y Ejemplo de Manejo de un Vector de Hebras
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos 1 // Declaraci ó n y creaci ó n del vector de hebras .
2 MiHebra vh [] = new MiHebra [ numHebras ];
3
Java y Hebras 4 // Creaci ó n de las hebras .
Creación y
5 for ( int i = 0; i < numHebras ; i ++ ) {
Arranque 6 vh [ i ] = new MiHebra ( i ) ;
join
7 }
8
sleep 9 // Arranque de las hebras .
Thread-safe 10 for ( int i = 0; i < numHebras ; i ++ ) {
Errores
11 vh [ i ]. start () ;
Habituales 12 }
13
Hebras
Depend. y 14 // Espera a que todas las hebras terminen .
Hebras 15 for ( int i = 0; i < numHebras ; i ++ ) {
Independ.
16 try {
Cesión de 17 vh [ i ]. join () ;
CPU 18 } catch ( I n t e r r u p t e d E x c e p t i o n ex ) {
19 ex . p ri n tS ta ck T ra ce () ;
20 }
21 }
( 28/ 44)
EI1024
MT1024
Programación
Concurrente y
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos

Java y Hebras

Creación y
Arranque

join

sleep
Duérmete un Rato con el
Thread-safe

Errores
Habituales
Método sleep
Hebras
Depend. y
Hebras
Independ.

Cesión de
CPU

( 29/ 44)
EI1024
MT1024
Programación
Concurrente y Duérmete un Rato con el Método sleep
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos
Una hebra que ejecute el método Thread.sleep( n ) se
duerme durante aproximadamente n milisegundos.
Java y Hebras
¿La hebra dormirá exactamente n milisegundos? No.
Creación y
Arranque 1 Algunos Sistemas Operativos (SO) asignan una siesta
join mínima de entre 20 y 50 milisegundos.
sleep 2 Cuando la hebra despierta, todas las CPUs podrían estar
Thread-safe ocupadas. Justo antes de despertarse, algunos SO suben
Errores temporalmente la prioridad a la hebra para que coja
Habituales
rápidamente la CPU.
Hebras
Depend. y 3 La hebra puede ser despertada a mitad del sueño por
señales del SO u otros eventos.
Hebras
Independ.

Cesión de
CPU Ejemplo:

1 Thread . sleep ( 2000 L ) ; // Du é rmete durante 2 seg .

( 30/ 44)
EI1024
MT1024
Programación
Concurrente y Interrupción del Sueño
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos Durante la ejecución de todas las variantes del método
sleep, se puede activar la excepción
Java y Hebras InterruptedException. Por ello, es conveniente tratarla:
Creación y
Arranque

join 1 try {
2 Thread . sleep ( 300 L ) ;
sleep
3 } catch ( Interrup tedException ex ) {
Thread-safe
4 ex . printStackTrace () ;
Errores 5 }
Habituales

Hebras
Depend. y
Hebras La ejecución del catch indica que la hebra ha sido
Independ.
despertada antes de tiempo.
Cesión de
CPU
Importante: No es conveniente basar el correcto
funcionamiento de un programa en el método sleep.
( 31/ 44)
EI1024
MT1024
Programación
Concurrente y
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos

Java y Hebras

Creación y
Arranque

join

sleep
Código a Prueba de Hebras
Thread-safe

Errores
Habituales
(thread-safe)
Hebras
Depend. y
Hebras
Independ.

Cesión de
CPU

( 32/ 44)
EI1024
MT1024
Programación
Concurrente y Código a Prueba de Hebras (thread-safe)
Paralela
G. Quintana

Tema 04.
Conceptos

Para que un código (p. e. una clase) sea a prueba de


Básicos

hebras (thread-safe), debe cumplir dos condiciones:


Java y Hebras

Creación y
Arranque
1 Debe funcionar correctamente en aplicaciones monohebra
join
(una sola hebra).
sleep 2 Debe funcionar correctamente en aplicaciones multihebra
Thread-safe
(más de una hebra).
Errores
Habituales Para ello debe funcionar bien independientemente de la
Hebras velocidad relativa, planificación y temporización de las
Depend. y
Hebras hebras.
Independ.

Cesión de
Además, no debe permitir a las hebras caer en estados
CPU incorrectos o inválidos, ni violar precondiciones,
postcondiciones ni invariantes.

( 33/ 44)
EI1024
MT1024
Programación
Concurrente y
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos

Java y Hebras

Creación y
Arranque

join

sleep

Thread-safe Errores Habituales Básicos


Errores
Habituales

Hebras
Depend. y
Hebras
Independ.

Cesión de
CPU

( 34/ 44)
EI1024
MT1024
Programación
Concurrente y Error Habitual Básico: Compartición Inadvertida
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos

Java y Hebras

Creación y
Ejercicio: ¿Qué ocurrirá si las hebras (objetos de la clase
Arranque MiHebra) imprimen en pantalla el valor a.id?
join

sleep
1 Trabajo a = new Trabajo () ;
Thread-safe
2 for ( i = 0; i < n ; i ++ ) {
Errores 3 a . id = i ;
Habituales
4 new MiHebra ( a ) . start () ;
Hebras
Depend. y 5 }
Hebras
Independ.

Cesión de
CPU

( 35/ 44)
EI1024
MT1024
Programación
Concurrente y Error Habitual Básico: Compartición Supuesta
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos
Ejercicio: Supongamos que dos hebras de la siguiente clase
(con los valores de miId adecuados) arrancan
Java y Hebras
simultáneamente. ¿Qué aparece en pantalla?
Creación y
Arranque 1 class MiHebra extends Thread {
join 2 int miId , valor ;
sleep 3 public MiHebra ( int miId ) {
4 this . miId = miId ;
Thread-safe
5 }
Errores 6 public void run () {
Habituales
7 if ( miId == 0 ) {
Hebras
Depend. y
8 valor = 10;
Hebras 9 } else if ( miId == 1 ) {
Independ. 10 d u e r m e t e D u r a n t e M i l i s e g u n d o s ( 2000 L ) ;
Cesión de 11 System . out . println ( " valor : " + valor ) ;
CPU
12 }
13 }
14 }

( 36/ 44)
EI1024
MT1024
Programación Error Habitual Básico: Suposiciones sobre la
Concurrente y
Paralela
G. Quintana
Velocidad
Tema 04.
Conceptos
Básicos

Ejercicio: Supongamos que dos hebras con el siguiente


Java y Hebras
método run (y con valores adecuados de miId) arrancan
Creación y
Arranque simultáneamente. ¿Qué aparece antes en pantalla?
join

sleep 1 void run () {


Thread-safe 2 if ( miId == 0 ) {
Errores 3 System . out . println ( " pepe " ) ;
Habituales 4 } else if ( miId == 1 ) {
Hebras 5 d u e r m e t e D u r a n t e M i l i s e g u n d o s ( 2000 L ) ;
Depend. y
Hebras
6 System . out . println ( " juan " ) ;
Independ. 7 }
Cesión de 8 }
CPU

( 37/ 44)
EI1024
MT1024
Programación
Concurrente y
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos

Java y Hebras

Creación y
Arranque

join

sleep Hebras Dependientes y


Thread-safe

Errores
Habituales
Hebras Independientes
Hebras
Depend. y
Hebras
Independ.

Cesión de
CPU

( 38/ 44)
EI1024
MT1024
Programación
Concurrente y Método setDaemon
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos
Una hebra del tipo daemon es una hebra (auxiliar) cuya
única función es ayudar a otras.

Por tanto, la aplicación termina cuando sólo quedan


Java y Hebras

Creación y
Arranque hebras de este tipo.
Dicho de otra forma: Un programa Java termina cuando
join

sleep

Thread-safe
todas sus hebras no daemon han terminado.
Errores
Habituales Ejemplo de uso:
Hebras
Depend. y 1 public static void main ( String args [] ) {
Hebras
Independ. 2 MiHebra t = new MiHebra () ;
Cesión de
3 t . setDaemon ( true ) ;
CPU 4 t . start () ;
5 System . out . println ( " Fin del main . " ) ;
6 }

( 39/ 44)
EI1024
MT1024
Programación
Concurrente y Método setDaemon (Cont.)
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos
Es conveniente fijar el tipo (y otras características) antes
de que la hebra arranque.
Java y Hebras

Creación y
Arranque
Herencia: Por defecto (si no se emplea setDaemon), una
join
hebra hereda el tipo de su hebra creadora.
sleep
El programa principal es del tipo no daemon.
Thread-safe

Errores Por tanto, una hebra de la que no se especifique el tipo y


sea creada por el programa principal será del tipo no
Habituales

Hebras
Depend. y daemon.
Hebras
Independ.

Cesión de
El método System.exit( -1 ) termina siempre, tanto si
CPU hay funcionando hebras dependientes como
independientes.

( 40/ 44)
EI1024
MT1024
Programación
Concurrente y
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos

Java y Hebras

Creación y
Arranque

join

sleep

Thread-safe Cesión de CPU


Errores
Habituales

Hebras
Depend. y
Hebras
Independ.

Cesión de
CPU

( 41/ 44)
EI1024
MT1024
Programación
Concurrente y Cesión de CPU con el Método yield
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos
El estándar de Java no indica nada al respecto de un
quantum máximo de tiempo tras el cual una hebra pierde
Java y Hebras la CPU para dejarla a otra.
Creación y
Arranque Por tanto, el estándar ni obliga a que exista dicho
join quantum, ni obliga a que no exista.
sleep

Thread-safe
Por ello, si una hebra está realizando mucho cálculo
Errores
intensivo y ninguna operación de E/S, se recomienda que
Habituales
de vez en cuando (no a todas horas) ceda la CPU, por si
Hebras
Depend. y hay otras hebras listas.
Hebras
Independ.
Si la hebra no cede la CPU y se ejecuta en un
Cesión de
CPU mononúcleo-monoprocesador, puede que dicha hebra
retrase a las demás o incluso podría llegar a producir un
interbloqueo (deadlock).
( 42/ 44)
EI1024
MT1024
Programación
Concurrente y Cesión de CPU con el Método yield (Cont.)
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos

Java y Hebras El método yield indica al sistema que la hebra está


Creación y dispuesta a ceder temporalmente la CPU.
Arranque

join
1 Si hay otra hebra en estado listo, la CPU puede pasar a
sleep ésta y la hebra original pasará al estado listo.
Thread-safe 2 Si no hay otra hebra en estado listo, la hebra que ha
Errores llamado al método yield continuará en ejecución.
Habituales

Hebras
Depend. y En resumen, la ejecución del método yield activa al
Hebras
Independ.
planificador (scheduler ) y éste puede elegir a otra hebra o
Cesión de no.
CPU

( 43/ 44)
EI1024
MT1024
Programación
Concurrente y Cesión de CPU con el Método yield (Cont.)
Paralela
G. Quintana

Tema 04.
Conceptos
Básicos

Java y Hebras El comportamiento exacto de yield puede variar según el


Creación y Sistema Operativo (Windows, Linux, etc.) o según la
Arranque
versión de JVM (1.5, 1.6, etc.).
join

sleep Puede esperar a que todas las demás hebras hayan tomado
Thread-safe un quantum, o a que hayan tomado un quantum sólo las
Errores hebras con la misma prioridad, etc.
Habituales

Hebras
Depend. y
No es obligatorio usar el método yield en todas las
Hebras
Independ.
aplicaciones, pero en algunos casos es muy recomendable
Cesión de
e incluso necesario.
CPU

( 44/ 44)

También podría gustarte