• No se han encontrado resultados

Revisión del Concepto de Hilo (Thread) API Java parathreads: Marco General. Clase Thread: API Básica. TEMA 3: Creación y Control De Threads en Java

N/A
N/A
Protected

Academic year: 2021

Share "Revisión del Concepto de Hilo (Thread) API Java parathreads: Marco General. Clase Thread: API Básica. TEMA 3: Creación y Control De Threads en Java"

Copied!
8
0
0

Texto completo

(1)

1

CONTENIDO

Revisión del Concepto de Hilo

Técnicas de Creación de Hilos

Ciclo de Vida. Control de Hilos

Prioridades

Hilos y Sistemas Operativos

BIBLIOGRAFÍA RECOMENDADA:

[Eck02] Eckel, B. Thinking in Java. Prentice Hall. 2002

[Göe06] Göetz et al. Java Concurrency in Practice, 2006

[Oaks04] Oaks & Wong. Java Threads. O`Reilly, 2004.

TEMA 3: Creación y Control De Threads en Java

2

ƒ

Dentro de un proceso, el control suele seguir un hilo de ejecución, que comienza

con main, continúa con el resto de las instrucciones, y termina con el proceso.

ƒ

Java soporta varios hilos de ejecución y por tanto, los programas de Java pueden

crear dentro de sí mismos varias secuencias de ejecución concurrentes.

ƒ

A diferencia de los procesos concurrentes, que son independientes, los hilos de un

mismo procesocomparten el espacio de direcciones virtuales, y los recursos del s.o.

ƒ

Por tanto, cada hilo tiene acceso a los datos y procedimientos del proceso, pero poseen supropio contador de programa y pila de llamadasa procedimientos.

ƒ

Los problemas que aparecen con una concurrencia multihilo son los habituales:

exclusión mutua y sincronización, y con menor importancia, esquema de prioridades e interbloqueos.

ƒ

Se pueden tener hilos de dos formas: herencia de la clase Thread o implementación de la interfaz Runnable.

Revisión del Concepto de Hilo (Thread)

Thread Clase Extendida

extends

© Antonio Tomeu Creación y Control de Thread en Java

3

„

Estamos en programación

concurrente… y toca usar hilos

„

Se optimiza el uso de la CPU

„

Se modelan mejor determinados

problemas… o no

„

El problema no admite otra solución

razonable, por ejemplo

…

programar un servidor decente

…

diseñar un GUI interactivo

Razones para Usar Hilos…

© Antonio Tomeu Creación y Control de Thread en Java 4

Thread void run() void start() ... Thread() Thread(Runnable target)

subclase

implementación

MiThread void run() { ... } RunnableObject void run()//imp. { ... } parámetro

Runnable

implements

void run()

API Java paraThreads: Marco General

extends

5

public class Thread extends Object

implements Runnable {

public Thread();

public Thread(String name);

public Thread(Runnable target);

public Thread(Runnable target,

String name);

public Thread(Runnable target,

String name, long stackSize);

public void run();

public void start();

public void join()

...

}

Clase Thread: API Básica

© Antonio Tomeu Creación y Control de Thread en Java 6

class Ejemplo_Hilos1

extends Thread

{

public Ejemplo_Hilos1 (int Tope) //constructor {T = Tope;}

public void run () //sobreescritura del metodo run

{

for (int i = 1; i <= T; i++)

System.out.println (i); //aquí comportamiento del } //hilo deseado private int T ;

}

Concurrencia con Hilos por Herencia de la clase

Thread

(2)

7 class Prueba_Hilo1 //Hace uso de la clase anterior {

public static void main (String [] args) throws InterruptedException

{

Ejemplo_Hilos1 Hilo1 = new Ejemplo_Hilos1 (5);

Ejemplo_Hilos1 Hilo2 = new Ejemplo_Hilos1 (15);

Hilo1.start (); //Ahora se lanzan ambos hilos... Hilo2.start (); //con apertura de co-rutina

Hilo1.join ();

Hilo2.join (); // y cierre de co-rutina System.out.println ("Hilos terminados"); }

}

© Antonio Tomeu Creación y Control de Thread en Java 8

Secuencia Temporal de Co-rutina con Hilos

Tiempo

E

J

E

C

U

C

I

Ó

N

Programa principal Hilo 1 Hilo 2

Condición

de Espera

(join)

© Antonio Tomeu Creación y Control de Thread en Java

9

„

Dado el código anterior, incremente el número de hilos y

el número de vueltas que cada hilo da. Recompile y

ejecute.

„

¿Observa entrelazado en la salida?

„

Continúe aumentando el número de hilos (por ejemplo

definiendo un array de hilos)

„

¿Dónde está el límite práctico al número de hilos (% uso

de CPU próximo al 100%)?

„

Escriba un “hola mundo” concurrente.

EJERCICIOS

© Antonio Tomeu Creación y Control de Thread en Java 10

Revisitando incConcurrente.java

„

Descárguelo (Tema 1)

„

Array de Threads

„

Dato común: n

„

Variables static

permiten compartir

memoria entre threads

„

Secciones críticas

„

Condición de

Concurso

„

Resultados no

consistentes

Modelo de Memoria de Java

© Antonio Tomeu Creación y Control de Thread en Java

public class Hola_Adios extends Thread {

public Hola_Adios (String Palabra) {Cadena = Palabra;}

private void otrometodo()

{System.out.println (“otro metodo”);} public void run ()

{ for (;;)

System.out.println (Cadena);

this.otrometodo(); // run puede invocar otros metodos de la clase

Integer p = new Integer(3); //o crear los objetos que necesita

}

public static void main (String [] args) {

new Hola_Adios ("Hola").start (); new Hola_Adios ("Hola").start (); new Hola_Adios ("Hola").start (); new Hola_Adios ("Adios").start (); }

„

Escriba un hilo que muestre pares o impares, según se indique en

el constructor, un número dado de veces, que también se indicará

en el constructor. Llame a la clase ParImpar.java

„

Escriba ahora un código que hago uso de la clase anterior. Llámelo

Usa_ParImpar.java

Observe el entrelazado.

„

Aloje una variable compartida en una clase llamada

Critica.java

. Provea métodos para incrementar la variable y

para mostrar su contenido. ¿Habría condiciones de concurso?

„

Escriba ahora hilos que utilicen un objeto común de esa clase.

„

Láncelos en un código aparte. ¿Observa algo raro?

„

Aunque no lo observe ¿Qué puede ocurrir potencialmente?

„

Realmente ¿hacía falta la clase Critica.java?

(3)

13

public interface Runnable

{

public void run();

}

…

Es una interface de java.lang

…

Cualquier clase X que la implemente expresa

ejecución concurrente

…

Objetos de la clase X son parámetros del

constructor de Thread

Concurrencia con Hilos por Implementación de la

Interfaz Runnable

© Antonio Tomeu Creación y Control de Thread en Java 14

public class X

implements Runnable {

... public void run()

{ //codigo concurrente } } A = new X() Objeto clase X contiene código concurrente H = new Thread(A) Código concurrente en ejecución A H H.start() A

© Antonio Tomeu Creación y Control de Thread en Java

15

public class UsoRunnableimplements Runnable

{

private String Cadena;

public UsoRunnable(String Palabra) {Cadena=Palabra;}

public void run()

{ for(;;)

System.out.println(Cadena); }

public static void main(String[] args) {

UsoRunnable Hilo1 = new UsoRunnable("Hola");

UsoRunnable Hilo2 = new UsoRunnable("Adios");

new Thread(Hilo1).start();

new Thread(Hilo2).start(); }

}

Concurrencia con Hilos por Implementación de la

Interfaz Runnable

© Antonio Tomeu Creación y Control de Thread en Java 16

/*Otra forma de crear hilos concurrentes dandoles nombre *@author Antonio J. Tomeu

*/

public class UsoRunnable2implements Runnable

{

private int Iter;

public UsoRunnable2(int Dato) {Iter = Dato;}

public void run() {

for(int i=1;i<=Iter;i++) System.out.println("Trabajando"); }

public static void main(String[] args) throws InterruptedException {

Runnable HiloA = new UsoRunnable2(100); Runnable HiloB = new UsoRunnable2(200); Runnable HiloC = new UsoRunnable2(100);

© Antonio Tomeu Creación y Control de Thread en Java

17

//version del constructor Thread crea hilo con un nombre Thread A = new Thread(HiloA, "Mi Hilo");

Thread B = new Thread(HiloB, "Tu Hilo"); //sin nombre Thread C = new Thread(HiloC);

A.start(); B.start(); A.join(); B.join(); C.join();

//metodo getName() de objetos de la clase Thread devuelve el nombre //del hilo

System.out.println(A.getName()); System.out.println(B.getName());

//no tenia nombre, pero se le dio uno en tiempo de ejecucion. System.out.println(C.getName());

} }

© Antonio Tomeu Creación y Control de Thread en Java 18

ƒ

Inconveniente de heredar de Thread: No permite heredar

de otras clases.

ƒ

Alternativa

de creación de hilos: Implementación de la

interfaz Runnable

ƒ

Sobreescribir siempre el método run

ƒ

Los objetos que implementan Runnable deben ser

lanzados

explícitamente

ƒ

Se hace creando un objeto Thread cuyo parámetro es un

objeto Runnable

ƒ

Luego se llama al método start del objeto Thread

creado

ƒ

Técnica recomendada: implementar la interfaz

mparativa de Métodos de Multithreading

(4)

19 „

Escriba ahora código de hilo que implemente la interfaz Runnable.

Déle al hilo acceso compartido a una variable común. Llámelo

hiloRunn.java

„

Escriba un programa que haga uso de los hilos anteriores. Llámelo

usahilRunn.java. Verifique la sobreescritura.

„

Escriba código de hilo para el lanzamiento de una co-rutina. Cada

hilo deberá desplegar su nombre. Desarrolle una versión con cada

herramienta de creación de hilos. Llámelas Co_rutina_T.java y

Co_rutina_I.java

„

Inspeccione el API de la clase Thread. En C/C++, el API de

pthread.h

incluye herramientas de sincronización mediante

mutex. ¿Puede decirse lo mismo de la clase Thread en java?

„

Finalmente, desarrolle una versión en java del algoritmo de Lamport

para dos procesos utilizando hilos heredados de Thread .

EJERCICIOS

© Antonio Tomeu Creación y Control de Thread en Java 20

Otras técnicas de creación de Threads

„

Pool de Threads

„

Permiten reutilizar hilos

„

Deben ajustarse (tuning) según aplicación

„

Análisis en Tema 6

© Antonio Tomeu Creación y Control de Thread en Java

21 Hilo Inexistente Hilo nuevo Ejecutable Bloqueado Muerto start()

new Thread(), new Thread(Runnable t)

recolección de basura wait(), join() notify(), notifyAll() destroy()-fin_ejecución //derogado destroy()//derogado destroy()//derogado Hilo Inexistente

Objetos Thread: Ciclo de Vida

22

CLASEThread: API DE CONTROL

ƒ Un hilo t1 puede se controlado por otro hilo t0 (normalmente el hilo padre) a través de los siguientes métodos de la clase Thread.

Pasa a t1 de en ejecución a listo. t1.yield()

Suspende a t1 durante t milisegundos. t1.sleep(int t)

Mata a t1. DEROGADO

t1.destroy ()

Suspende a t0 y espera a que termine t1. t1.join ()

Envía una señal a t1. t1.interrupt ()

Hace que t1 vaya de bloqueado a listo. DEROGADO

t1.resume ()

Envía a t1 de listo/en ejecución a bloqueado. t1.suspend ()

Comprueba si el hilo t1 está vivo. t1.isAlive()

Mata al hilo t1. DEROGADO

t1.stop ()

Lanza el hilo t1 t1.start ()

Determina si t0 tiene permiso para controlar a t1.

t1.checkAccess()

Comportamiento Método

© Antonio Tomeu Creación y Control de Thread en Java

import java.io.*; Import java.util.*;

public class Control extends Thread {

//No declara constructor explicito. Usa el disponible por defecto public void run()

{

for(;;)

System.out.println("Trabajando"); }

public static void main(String[] args) throws IOException

{ int c;

//usando el constructor implicito Control Hilo = new Control(); Hilo.start();

CONTROL DE Threads: Ejemplo con Métodos Derogados

for(int i=1; i<=100; i++) //entrelazado de instrucciones System.out.println("Hola soy el padre");

Hilo.suspend(); //USO DE METODO DEROGADO, HILO PADRE SUSPENDE A HIJO .

System.out.println("Hijo suspendido"); //Ahora reactivamos al hijo, que pasa a listo. System.out.println("Pulsa 1 para despertar al hijo"); do {

c=System.in.read(); }

while(c != -1);

Hilo.resume(); //USO DE METODO DEROGADO, PASA A LISTO A HIJO

//un poquito de interfoliacion otra vez. for(int i=1; i<=100; i++)

System.out.println("Hola soy el padre");

Hilo.stop(); //USO DE METODO DEROGADO, PADRE PARA AL HIJO

} }

(5)

25

import java.io.*;

public class AutoControl extends Thread {

private int Vueltas; public AutoControl(int Dato) {Vueltas=Dato;}

public void run()

{ //el uso de sleep exige capturar la posible excepcion. try{

for(int i=1; i<=Vueltas; i++){ System.out.println(i);

if(i==25){//los hilos se suspenden en la iteracion 25 System.out.println("Suspension durante dos segundos"); int timeout = 1000;

sleep(timeout);

System.out.println("Continuando"); }//if

}//for

}catch (InterruptedException e) {return;} }

© Antonio Tomeu Creación y Control de Thread en Java

CONTROL DE Threads: Ejemplo de Replanificación Voluntaria (sleep)

26

public static void main(String[] args) {

new AutoControl(50).start(); new AutoControl(150).start(); }

}

© Antonio Tomeu Creación y Control de Thread en Java

27 public class replaniYield

extends Thread {

private boolean hY;//indicara si el hilo cede prioridad o no… private int v;

public replaniYield(boolean hacerYield, int vueltas) {hY = hacerYield; v = vueltas;}

public void run() {

for(int i=0; i<v; i++)

if(i==20&&hY==true){this.yield();}//indica cesion de prioridad… else System.out.println("Hilo "+this.getName()+" en iteracion "+i); }

public static void main(String[] args) {

replaniYield h0 = new replaniYield(false, 50); replaniYield h1 = new replaniYield(false, 50);

replaniYield h2 = new replaniYield(true , 50); //cedera prioridad y h0.setName("1-NoYield"); //sera o no considerarda h1.setName("2-NoYield"); h2.setName("3-SIYield");

h0.start(); h1.start(); h2.start(); }

}

CONTROL DE Threads: Ejemplo de Cesión de Prioridad Voluntaria (yield)

© Antonio Tomeu Creación y Control de Thread en Java 28

CONTROL DE PRIORIDAD

ƒ

Prioridad hilo hijo igual a la de hilo padre

ƒ

La prioridad tiene sentido

exclusivamente

en el ámbito de la

JVM… aunque se mapea a los hilos de sistema (

OJO: EL

MAPPING NO ES RIGUROSO=>INVERSIONES DE

PRIORIDAD

)

ƒ

Clase Thread:esquema de diez niveles de prioridad

ƒ

Ver la prioridad de un hilo:

ƒ

public int getPriority()

ƒ

Alterar la prioridad de un hilo:

ƒ

public void setPriority(int p) (1<=p<=10)

© Antonio Tomeu Creación y Control de Thread en Java

29

package java.lang;

public class Thread implements Runnable

public final static int Thread.MIN_PRIORITY;

public final static int Thread.NORM_PRIORITY;

public final static int Thread.MAX_PRIORITY;

public void setPriority(int prioridad);

public int getPriority():

CLASE Thread: API DE CONTROL DE PRIORIDAD

© Antonio Tomeu Creación y Control de Thread en Java 30

PLANIFICACIÓN BASADA EN PRIORIDADES

„

Valor prioridad en JVM indica al planificador

del S.O qué hilos van primero…

„

pero

no es un contrato absoluto

entre

ambos ya que depende:

…

de la implementación de la JVM

…

del S.O. subyacente

…

del mapping prioridad jvm-prioridad s.o.

(6)

31 public class Prioridades extends Thread

{

private long dato;

private static int prio = 4; //atributo de clase comun a instancias public Prioridades (long n){dato=n;}

private long fac(long n) {

if (n == 0) return 0; else if (n == 1) return 1;

else return(fac(n-1)*n); }

public void run() {

//this.setPriority(prio++); //ejecutar con y sin el ajuste de prioridad System.out.println("El factorial de "+dato+" es "+fac(dato)); }

public static void main(String[] args) {

new Prioridades(10).start(); //orden lanzamiento no es igual al orden new Prioridades(20).start(); //de ejecución… pero

new Prioridades(30).start(); //¿ajustando las prioridades? new Prioridades(40).start();

new Prioridades(50).start(); new Prioridades(60).start(); }

}

© Antonio Tomeu Creación y Control de Thread en Java 32

import java.util.*; import java.text.*;

public class Trabajo implements Runnable { long n;

String id;

private long fib(long n) { if (n == 0)

return 0L; if (n == 1)

return 1L;

return fib(n - 1) + fib(n - 2); }

public Trabajo(long n, String id) { this.n = n;

this.id = id; }

public void run() { Date d = new Date();

DateFormat df = new SimpleDateFormat("HH:mm:ss:SSS"); long startTime = System.currentTimeMillis(); d.setTime(startTime);

System.out.println("Iniciando trabajo " + id + " a las " + df.format(d)); fib(n);

long endTime = System.currentTimeMillis(); d.setTime(endTime);

System.out.println("Acabando trabajo " + id + " a las " + df.format(d) + " tras " + (endTime - startTime) + " milliseconds");

} }

33

public class ThreadTest {

public static void main(String[] args) { int nHilos = Integer.parseInt(args[0]); long n = Long.parseLong(args[1]); Thread t[] = new Thread[nHilos]; for (int i = 0; i < t.length; i++) {

t[i] = new Thread(new Trabajo(n, "Trabajo " + i)); t[i].start();

}

for (int i = 0; i < t.length; i++) { try {

t[i].join();

} catch (InterruptedException ie) {} }

} }

© Antonio Tomeu Creación y Control de Thread en Java 34

public class ThreadTestNuevaPrioridad { public static void main(String[] args) {

int nHilos = Integer.parseInt(args[0]); long n = Long.parseLong(args[1]); Thread t[] = new Thread[nHilos]; for (int i = 0; i < t.length; i++) {

t[i] = new Thread(new Trabajo(n, "Trabajo " + i));

t[i].setPriority((i % 10)+1);

t[i].start(); }

for (int i = 0; i < t.length; i++) { try {

t[i].join();

} catch (InterruptedException ie) {} }

} }

© Antonio Tomeu Creación y Control de Thread en Java

„

Compile y ejecute los códigos anteriores

„

¿Observa inversiones de prioridad?

„

¿A qué cree que se deben?

„

Desarrolle ahora código de hilo

sincronizado basado en prioridades (p.e. un

hilo incrementa un dato y otro lo muestra,

en ese orden)

„

¿Es una estrategia válida de

sincronización?

„

¿Y con una co-rutina?

EJERCICIOS

„

El s.o. conoce el número de hilos que

usa la JVM

„

Se aplican uno-a-uno. (JVM a Win)

„

El secuenciamiento de hilos java está

sujeto al del s.o.

„

Se aplican 10 prioridades en la JVM

sobre 7 en el s.o.+5 prioridades de

secuenciamiento

(7)

37

MAPPING PRIORIDADES JVM A WIN32

THREAD.PRIORITY_TIME_CRITICAL 10 (Thread.MAX_PRIORITY) THREAD.PRIORITY_HIGHEST 9 THREAD.PRIORITY_HIGHEST 8 THREAD.PRIORITY_ABOVE_NORMAL 7 THREAD.PRIORITY_ABOVE_NORMAL 6 THREAD.PRIORITY_NORMAL 5 (Thread.NORM_PRIORITY) THREAD.PRIORITY_BELOW_NORMAL 4 THREAD.PRIORITY_BELOW_NORMAL 3 THREAD.PRIORITY_LOWEST 2 THREAD.PRIORITY_LOWEST 1 (Thread.MIN_PRIORITY) THREAD.PRIORITY_IDLE 0 Prioridad Win32 Prioridad Java

© Antonio Tomeu Creación y Control de Thread en Java 38

„

Pero recuerde…

„

En general, hilos de baja prioridad

obtendrán acceso al procesador

cuando los de alta prioridad estén en

espera.

„

La

prioridad es poco significativa

cuando todos los hilos compiten por el

procesador.

MAPPING HILOS JVM-HILOS NATIVOS DE WIN32

© Antonio Tomeu Creación y Control de Thread en Java

39

„

Núcleos recientes implementan Native

Posix Thread Library

„

Aplican hilos JVM a hilos del núcleo

uno-a-uno bajo el modelo de Solaris

„

La

prioridad java es un factor muy

pequeño

en el cálculo global del

secuenciamiento

MAPPING HILOS JVM-HILOS NATIVOS DE LINUX

© Antonio Tomeu Creación y Control de Thread en Java 40

MAPPING PRIORIDADES JVM A PRIORIDADES

DE HILOS LINUX

-5 10 (Thread.MAX_PRIORITY) -4 9 -3 8 -2 7 -1 6 0 5 (Thread.NORM_PRIORITY) 1 4 2 3 3 2 4 1 (Thread.MIN_PRIORITY) no contemplado 0

Prioridad Linux (nice value) Prioridad Java

© Antonio Tomeu Creación y Control de Thread en Java

41

„

Solo como root

(o con privilegios

equivalentes, setuid)

„

Parametrizar a la JVM indicando que

tenga en cuenta las prioridades.

RESTRICCIONES DEL MAPPING PRIORIDADES JVM A LINUX

© Antonio Tomeu Creación y Control de Thread en Java 42

„

La actual especificación de la JVM

no

establece un modelo de planificación por

prioridades

„

El comportamiento puede y debe variar en

diferentes máquinas

„

En secuencias de tareas estrictas, no es

posible planificar con prioridades

„

Aunque sí con co-rutinas, a nivel básico

CONTROL DE PRIORIDAD: CONCLUSIONES

(8)

43

„

Modelos Teóricos de Control de la

Concurrencia

„

Variables Comunes

„

Semáforos

„

Regiones Críticas

„

Monitores

En el Próximo Tema…

Referencias

Documento similar

64. J.), J.: Direcciones pontificias. J.), J.: El Estado Corporativo. DE I,A CRUZ : La Propiedad.. J.), J.: Orientaciones cristianas del Fuero del Tra- bajo. GAIXART FOLCH, A.:

The extended StateML + meta-model and tools now include many improvements over the previous versions, being these the most important: (1) the addition of regions, which enable

The general idea of the language is to “thread together,” so to speak, existing systems that parse and analyze single web pages into a navigation procedure spanning several pages of

calling other (public or private) methods from the same object (from himself) or calling other methods from other objects (public or accessible from that

public static void main(String[] args) { String counterFile = args[0];. int initialValue

– Los motes de los emblemas, las citas de epigramas, dísticos y otros textos (filacterias, pies de estampas, etc.) deberán ir entre comillas siempre, y

El formato general del documento principal será de un diseño de hoja de tamaño DIN-A4, 3cm de margen en todos los lados, fuente Times New Roman, interlineado 1,5 líneas, sin espaciado

Introduzca el texto, recordando no alterar el formato preestablecido en esta planilla; de modo que, no separe párrafos con ningún espacio (el formato ya está configurado de