Threads, hilos en java

download Threads, hilos en java

of 47

Transcript of Threads, hilos en java

  • 7/21/2019 Threads, hilos en java

    1/47

  • 7/21/2019 Threads, hilos en java

    2/47

    ! Si sustituimos el mtodo run()por el mtodo start()

    este crea un nuevo clase y ejecuta el mtodo run().

    import java.applet.Applet;

    public class OurApplet extends Applet

    {

    public void init()

    {

    OurClass oc = new OurClass();

    oc.start();

    }

    }

    Tiempo

    Ejecucin run()

    Applet ejecuta run()

    Applet ejecuta init()

    Applet antes de init()

    Applet antes de init()

    Applet ejecuta init()

    Applet ejecuta start()

    Thread ejecuta run()

    Ejecucin run()

    Tiempo

    ! run():El mtodo run() contendr el cdigo que se ejecuta.! start(): Crea un nueva clase y ejecuta el mtodo run de la

    clase.! static void sleep(long milisegundos).! static void sleep(long milisegundos, int nanosegundos).

    Detiene la ejecucin durante un tiempo.

  • 7/21/2019 Threads, hilos en java

    3/47

    Interface Runnable

    ! El interface Runnablecontiene un nico mtodo run.

    ! Se puede implementar directamente Runnable sin heredar deThread

    public class OurClass implements Runnable

    {

    public void run()

    {

    for (int i=0; i

  • 7/21/2019 Threads, hilos en java

    4/47

    Ej: Parpadeo en animaciones:

    ! Incluir un soporte de interface Runnableproporciona elcomportamiento en el applet para implementar un thread.

    import java.awt.Graphics;import java.awt.Color;

    import java.awt.Font;

    public class HolaMundoSwirl extends

    java.applet.Applet implements Runnable{

    Font f = new Font("TimesRoman",Font.BOLD,48);

    Color colors[] = new Color[50];

    Thread runThread;

    public void start(){

    if(runThread == null){

    runThread = new Thread(this);runThread.start();

    }

    }

    public void stop(){

    if(runThread != null){

    runThread.stop();

    runThread = null;

    }

    }

    public void run(){

    float c =0;

    for (int i=0;i

  • 7/21/2019 Threads, hilos en java

    5/47

    try{

    Thread.currentThread().sleep(50);}

    catch (InterruptedException e){ }

    if (i == (colors.length)) i = 0;

    }}

    public void paint(Graphics g){

    g.setFont(f);

    g.drawString("Hola Mundo!!!",15,50);

    }

    }

    ! En este caso se transforma el propio applet en un thread.

    ! No obstante cuando trabajemos con applets, no hay queconfundir el mtodo start() del applet con el mtodothread.start()del thread.

    ! Mtodo isActive(): determina si el apple est activo o no.Por definicin un applet est activo entre los mtodos start y stopdel applet.

    public void run() {

    while (isActive()) {

    try{

    repaint();

    Thread.sleep(1000);

    } catch (Exception e) {}

    }

    timer = null;

    }

    Lectura Asncrona

    ! Aparece un problema cuando leemos o escribimos en un ficheroo en un socket, ya que esta accin depende de otros recursos yasean programas o hardware.

  • 7/21/2019 Threads, hilos en java

    6/47

    ! Estos recursos pueden no estar disponibles temporalmente. Asmismo, no existe en el API de Java dispositivos que compruebenesto.

    !

    El uso de threads pueden bloquearse esperando datos mientrasque la ejecucin del applet no es alterada.

    ! Lectura de Sockets.

    import java.io.*;

    import java.net.*;

    public class AsyncReadSocket extends Thread

    {

    private Socket s;

    private StringBuffer result;

    public AsyncReadSocket( Socket s)

    {

    this.s = s;

    result = new StringBuffer();

    }

    public void run()

    {

    DataInputStream is = null;

    try

    {

    is = new

    DataInputStream(s.getInputStream());

    } catch (Exception e) {}

    while (true){

    try

    {

    char c=is.readChar();result.append;

    } catch (Exception e) {}

    }

    }

  • 7/21/2019 Threads, hilos en java

    7/47

    public String getResult(){

    String retval = result.toString();result = new StringBuffer();

    return retval;}

    }

    ! El mtodo run de este thread lee caracteres desde un socketalmacenndolo en un StringBuffer.

    ! El applet llamara a getResultpara obtener cualquier dato quese halla leido, devolviendo un String vacio si no hay datos.

    ! Posibles colisiones cuando el applet llama a getResult almismo tiempo que readChar de vuelve un dato, accediendoambos a la instancia result.

    ! Veamos una posible ejecucin.

    Tiempo

    Thread lee un dato

    Thread Bloqueado

    Applet llama a

    getResult()

    Applet ejecutando

    otras tareas

    ! Secuencia de eventos:

    1. El applet entra en getResult()2. Es asignado a retvalel valor del StringBuffer.3. El Thread del socket finaliza la ejecucin de readChar4. El Thread del socket aade el char ledo al StringBuffer.5. El applet asigna a result un StringBuffer vaco (con new).

  • 7/21/2019 Threads, hilos en java

    8/47

    Estados de un Thread

    Periodo durante stop()Periodo durante start()

    Not Running

    Running

    ! La clase Thread provee el mtodo isAlive(),para saber si unthread esta ejecutndose o no. Este est vivo algo antes el definalizar el start(),hasta algo despus de finalizar stop().

    ! Se usa tambin para determinar si el mtodo run se hacompletado.

    ! Por ejemplo, en la clase AsyncReadSocket pueden llegar datos

    despus de haber sido llamado el mtodo stop().

    ! Mtodo stop(): Se utiliza para parar un thread.

    Ejemplo de start() y stop()

    import java.applet.Applet;

    public class MyApplet extends Applet

    {

    Thread t;

    Public void start()

    {

    t = new TimerThread(this,500);

    t.start();

    }

  • 7/21/2019 Threads, hilos en java

    9/47

    public void stop()

    {

    t.stop();

    while (t.isAlive()){

    try

    {

    Thread.sleep(100);

    } catch (InterrumptedException e){}

    }

    }

    }

    ! Mtodo suspend(): Se utiliza para suspender temporalmenteun thread.

    ! Mtodo resumen(): Se utiliza para revivir una tareasuspendida. Suele llamarse despus de suspend()para que latarea vuelva a ejecutarse.

    Ejemplo:

    Public class java1005 extends Applet implements

    Runnable{

    Thread t;

    ....

    class ProcesoRaton extends MouseAdapter{

    Boolean suspendido;

    Public void mousePressed( MouseEvent evt){

    If(suspendido) t.resume();else t.suspend();

    Suspendido = !suspendido;

    }

    }

  • 7/21/2019 Threads, hilos en java

    10/47

    ! Mtodo join(): Espera la finalizacin de un thread. Pordefinicin join regresa tan pronto como el thread se considera"not alive".

    ! joint(long timeout): Espera la finalizacin de un threaddurante un tiempo determinado.

    ! joint(long timeout, int nanos): Igual que el anteriorpero con nanosegundos.

    Ejemplo de joint()

    public class MyApplet extends Applet

    { Thread t;

    Public void start()

    {

    t = new TimerThread(this,500);

    t.start();

    }

    public void stop()

    {

    t.stop();

    try

    {

    t.join();

    } catch (InterrumptedException e){}

    }

    ! currentThread(): devuelve el objeto thread que representael tarea que se est ejecutando actualmente.

    ! yield(): Hace que el intrprete cambie de contexto entre latarea actual y la siguiente tarea ejecutable. Es una manera deasegurar que las tareas de menor prioridad no sufran inanicin.

  • 7/21/2019 Threads, hilos en java

    11/47

    ! static int enumerate(Thread threadArray[]):

    Obtiene todos los threads en ejecucin y los almacena en un

    array. Devuelve el nmero de threads almacenados en el array.

    ! static int activeCount(): Devuelve el nmero dethreads en el programa.

    Ejemplo de enumerate() y activeCount():

    import java.applet.*;

    import java.awt.*;

    public class Animate extends Applet{

    public void printThreads(){

    Thread ta[]= new Thread[Thread.activeCount()];

    int n = Thread.enumerate(ta);

    for (int i=0;i

  • 7/21/2019 Threads, hilos en java

    12/47

    ! setName(): Asigna un nombre a una instancia de un thread.

    ! getName(): Obtiene el nombre de una instancia del thread

    actual.

    Ejemplo de setName()

    import java.awt.*;

    public class TimerThread extends Thread{

    Component comp; // componente a repintar

    int timediff; // tiempo entre repintado

    public TimerThread(Component comp,int timediff){

    this.comp=comp;

    this.timediff=timediff;

    setName("TimerThread(" + timediff +

    "milliseconds)");

    }

    public void run(){

    while (true){

    try{

    comp.repaint();

    sleep(timediff);

    }catch(Exception e){}}

    }

    }

    ! En esta versin de la claseTimerThread, asignamos un nombreal thread en el constructor.

    ! El nombre es TimerThread + milisegundos transcurridos.Posteriormente puede llamarse a getName().

    ! El uso de nombres almacena informacin extra que puedeusarse para la depuracin del programa y identificacin de losdistintos threads del programa.

    ! Si queremos saber el thread que est en estos momentos enejecucin solo tenemos que insertar un sentencia como lasiguiente:

    String reader = Thread.currentThread().getName();

  • 7/21/2019 Threads, hilos en java

    13/47

    3. Sincronizacin.

    ! Los threads son independientes, contienen todos los datos ymtodos que necesitan para su ejecucin y no necesitan ningn

    mtodo exterior.! Solucionar el problema de acceso a variables compartidas.

    ! Ejemplo 1: cuenta bancaria.

    1) comprobar que el usuario tiene suficiente dinero en la cuentacomo indica. Si no lo tiene ir al paso 4.

    2) Sacar el dinero de la cuenta.3) Dar el dinero al usuario.4) Imprimir el recibo.

    Public class AutomatedTellerMachine extens Teller

    {

    public void withdraw( float amount)

    {

    Account a = getAccount();

    if (a.deduct(amount))

    dispense(amount);printReceipt();

    }

    }

    public class Account

    {

    private float total;

    public boolean deduct(float f)

    {if (t

  • 7/21/2019 Threads, hilos en java

    14/47

    ! Supongamos dos threads A y B accediendo a la misma cuenta.

    1) A comienza la ejecucin del mtodo deduct.2) A confirma que tiene dinero. (if t

  • 7/21/2019 Threads, hilos en java

    15/47

    Ejemplo 2: revisin de AsyncReadSocket

    public void run() {DataInputStream is = null;

    try

    {

    is = new

    DataInputStream(s.getInputStream());

    } catch (Exception e) {}

    while (true)

    {

    try

    {

    char c=is.readChar();

    appendResult(c);

    } catch (Exception e) {}

    }

    }

    public synchronizedString getResult(){

    String retval = result.toString();result = new StringBuffer();

    return retval;

    }

    public synchronizedvoid appendResult(char c){

    result.append(c);

    }

    }

    ! Con la sincronizacin podemos serializar la ejecucin demtodos completos y bloques de cdigo.

  • 7/21/2019 Threads, hilos en java

    16/47

    Una clase Flag para sincronizar.

    ! Es realmente necesario el uso de la palabra clavesyncronized? Puede usarse un flag?

    Ejemplopublic class BusyFlag{

    private Thread busyflag = null;

    public void getBusyFlag()

    {

    while (busyflag != Thread.currentThread())

    {

    if (busyflag == null)

    busyflag= Thread.currentThread();

    try {

    Thread.sleep(100);

    } catch (Exception e){}

    }

    }

    public void freeBusyFlag()

    {

    if (busyflag == Thread.currentThread())

    busyflag = null;

    }

    }

    ! El mtodo getBusyflag se queda en un bucle hasta ponerbusyflag al thread actual esperando 100 milisegundos acontinuacin.

    ! El mtodo freeBusyFlag() libera el flag. Esta espera de 100milisegundos asegura que la operacin se ha terminado.

    ! En un sistema de 2 threads A y B ocurre el siguiente problema:1) Thread A detecta que busyflagesta libre.2) Thread B detecta que busyflagesta libre.3)B se apodera de busyflag.4) B espera 100 ms5) B sale confirmando que tiene el flag

    6) A se apodera del flag, espera 100ms, sale y confirma que tiene elflag.

  • 7/21/2019 Threads, hilos en java

    17/47

    ! Podemos usar esta clase en nuestra clase Account de cuentabancaria:

    public class Account

    {private float total;

    private flag = new BusyFlag();

    public boolean deduct(float f)

    {

    boolean succed= false;

    flag.setBusyFlag();

    if (t

  • 7/21/2019 Threads, hilos en java

    18/47

    }public synchronized void freeBusyFlag()

    {

    if(getBusyFlagOwner()==Thread.currentThread())

    { busyflag = null;

    }

    }

    ! Mtodos wait() y notify(): Al pertenecer a la claseObject, cualquier objeto hereda estos mtodos.

    ! wait(): En un bloque sincronizado, el thread se bloquea y

    entra en estado de espera hasta que se produzca un evento quele permita continuar.

    ! public final void wait(long timeout) throws

    InterruptedException: El thread espera hasta que esnotificado o se agota el tiempo en milisegundos.

    ! public final void wait() throws

    InterruptedException: Si el timeout es cero el threadesperar a la notificacin.

    ! public final void wait(long timeout, int nanos)

    throws InterruptedException: Se especifica en

    nanosegundos.

    ! Mtodo notify(): Despertar aquel thread que lleve mstiempo en estado de espera. Dicho thread continua la ejecucinen el punto en que se bloque.

    ! Mtodo notifyAll(): Si queremos despertar todos losthreads que estn esperando.

  • 7/21/2019 Threads, hilos en java

    19/47

    Ejemplo:

    import java.util.*;

    import java.io.*;

    public class Consumer extends Thread{

    protected Vector objects; // array de objetos

    public Consumer(){

    objects = new Vector();

    }

    public void run(){

    while (true){Object object = extract();//sacaobjeto

    System.out.println(object);

    }

    }

    protected Object extract(){

    synchronized (objects){ //bloqueamos array

    while (objects.isEmpty()){

    try{objects.wait();

    }catch (InterruptedException ex){

    ex.printStackTrace();

    }

    Object o =objects.firstElement();

    objects.removeElement (o);

    return o;

    }

    }

    public void insert (Object o){

    synchronized(objects){

    objects.addElement (o);

    objects.notify();

    }

    }

  • 7/21/2019 Threads, hilos en java

    20/47

    public static void main (String args[])

    throws IOException{

    Consumer c = new Consumer();

    BufferedReader i = newBufferedReader(new InputStreamRead);

    c.start;

    String s;

    while ((s = i.readLine ()) !=null){

    c.insert (s);

    Thread.sleep(1000);

    }

    }

    }

    Gestin de threads

    ! Cuando se crea un thread, se le asigna una prioridad (la hereda).

    ! El dispositivo que decide el orden de ejecucin en "tiempo real"de los threads se denomina scheduler.

    ! Existe diferentes maneras de realizar la gestin de los threads, yen Java no existe una uniformidad de criterios a la hora derealizar esta gestin.

    ! Ejemplo: Gestin de la CPU.class TestThread extends Thread{

    String id;

    public TestThread(String s){

    id = s;

    }public void run(){

    int i;

    for(i=0;i

  • 7/21/2019 Threads, hilos en java

    21/47

    public class Test{

    public static void main(String args[]){

    TestThread t1,t2,t3;

    t1 = new TestThread(Thread 1);

    t1.start();t2 = new TestThread(Thread 2);

    t2.start();

    t3 = new TestThread(Thread 3);

    t3.start();

    }

    }

    ! Asumimos que doCalc()es un mtodo computacionalmentecaro y requiere 5 segundos por llamada. Esto da lugar a lanecesidad de la gestin de los mismos.

    ! Todo thread en la maquina virtual ofrece estos cuatro estados:

    o Initial: Est en estado inicial cuando es creado, esto es, siel constructor es llamado bajo start().

    o Runnable: Un thread est en estado runnable una vez elmtodo start()ha sido llamado.

    o Blocket:Esto ocurre cuando el thread no est ejecutndosepero est esperando para que un evento especfico ocurra.

    o Exiting: Un thread esta en estod de existencia cuando elmtodo run()retorna o stop()es llamado.

    ! Mediante la mquina virtual solo podemos ejecutar un solothread a la vez, aunque es frecuente que el programa de Javatenga ms de un thread en estado runnable.

    ! Cuando esto sucede la mquina virtual selecciona entre el

    conjunto uno para ejecutar. El resto permanece en estadorunnable hasta que se produzca un cambio en el mtodo run()del thread en ejecucin.

    ! La clave est en cual de los threads en estado runnable esseleccionado para comenzar a ejecutarse.

    ! Para ello, Java establece un orden de prioridades asignando unnumero positivo de rango definido. Esta prioridad solo puede ser

    cambiada por el programador.

  • 7/21/2019 Threads, hilos en java

    22/47

    ! ATENCIN: La mquina virtual nunca cambia la prioridad de unthread, cuando cambia de estado o despus de que el threadhalla sido ejecutado durante un cierto periodo de tiempo.

    !

    Ej: Un thread de prioridad 5 mantiene esa prioridad desde eltiempo de creacin con varios cambios de estado entre runnabley blocket hasta que el thread termina o entra en estado exiting.

    ! Esto garantiza que el thread que esta en ejecucin, es aquel quemayor prioridad tiene. As, la maquina virtual detiene la ejecucinde un thread de baja prioridad ante la entrada en runtime de otrode ms alta cogiendo este ltimo.

    ! setPriority(int): Asigna a la tarea la prioridad indicadapor el valor pasado como parmetro.

    ! MIN_PRIORITY,NORM_PRIORITY y MAX_PRIORITY quetoman los valores 1,5,10 respectivamente.

    ! Usaremos NORM_PRIORITY para procesos a nivel de usuario,MIN_PRIORITY para entrada/salida en red y redibujar enpantalla.

    ! Con las tareas en las que se fije MAX_PRIORITY, hay que tenercuidado, ya que si no se hacen llamadas sleep()o yield(),se puede provocar que el intrprete Java quede fuera de control.

    ! get_Priority():Devuelve la prioridad de la tarea en curso,que es un valor comprendido entre 1 y 10.

  • 7/21/2019 Threads, hilos en java

    23/47

    Ejemplo incompleto de manejo de socket:

    public class SchedulingExample implements

    Runnable{

    public static void main(String args[]){Thread calcThread = new Thread (this);

    calcThread.setPriority(4);

    calcThread.start();

    AsyncReadSocket reader;

    reader = new AsyncReadSocket (new Socket(host,

    port));

    reader.setPriority(6);

    reader.start();

    doDefault();}

    public void run(){

    doCalc();

    }

    }

    ! Este programa tiene tres threads: primero, hay por defecto unthread que ejecuta el mtodo main(), el cual despus de

    crearse otros threads va ha ejecutar doDefault().Segundohay un thread de calculo calcThread que va ha ejecutardoCalc().Por ltimo, el lector AsyncReadSocket readerest leyendo un socket.

  • 7/21/2019 Threads, hilos en java

    24/47

    ! En T1 se ejecuta main()con prioridad NORM_PRIORITY=5y esel nico activo en la maquina virtual.

    ! En T2 se crea calcThreadcon prioridad 4 y llama a start().

    Ahora hay dos threads en estado runnablepero al ser inferioral primero se queda en espera en la CPU.

    ! El thread por defecto main()continua su ejecucin creando elthread readercon prioridad 6 que llama a start(). Comoahora readertiene mayor prioridad que el thread por defecto,reader comienza a ejecutarse y el thread de main()ycalcThreadse queda en espera. Llamaremos a este instanteT3.

    ! Ahora el thread readerejecuta readChar()dentro del mtodorun()de la clase AsyncReadSocket. Si no existe ningn datoreaderentra en estado blocket y se el thread de main()continua la ejecucin (instante T4) en el estado en que se habaquedado hasta que la entrada del dato de readChar()quedasatisfecha.

    ! En ese instante T5 pasa el thread readera estado runnable y

    como tiene mxima prioridad continua ejecutndose.

    ! Mientras calcThread ha estado pacientemente esperandopara cambiar a run y debe continuar esperando hasta el threadde main()y el thread readerpasen a estado bloquet o exiting

    ! Puede ocurrir que este thread nunca llegue a ejecutarseproducindose un CPU starvation. Es responsabilidad deJava developer, asegurarse que ningun thread este en estadostarve.

    ! La mquina virtual de Java, nunca ajustar la prioridad del threadpara compensar la perdida de desarrollo de la CPU.

  • 7/21/2019 Threads, hilos en java

    25/47

    Threads con igual prioridad

    ! Hay en la maquina virtual de Java 10 niveles de prioridad queconciernen por tanto a 13 listas de posiciones:

    o Uno de todos aquellos en el estado inicial.o Uno de todos aquellos en el estado blocked.o Uno de todos aquellos en el estado exiting.o Uno por cada nivel de prioridad.

    ! Si un thread en estado runnable con prioridad 7 esta en laposicin nmero 7, pero cuando el thread se bloquea, es movidoa la lista blocked.

    ! En Java no existe un ordenamiento cuando varios threads estnbloqueados.

    ! El sistema de bsqueda es el siguiente:o Comienza por mirar la lista con threads de prioridad 10. Si

    esta vaca, pasa a los de prioridad 9 hasta encontrar unposicin de la lista no vaca.

    o A continuacin, coge el primer elemento de la lista y loejecuta y mueve tambin ese thread al final de la lista.

    ! Volvamos al ejemplo anterior y supongamos que calcThreadtiene la misma prioridad que el thread por defecto main().

    ! En este caso en la posicin 5 tendremos la lista con los threadsmain()y calcThread de prioridad 5, mientras que readerestar en la lista de prioridad 6.

    ! En T2o PRIORITY 5: main() -> calcThread ->NULLo PRIORITY 6: NULLo BLOCKED:NULL

    ! Si la mquina virtual selecciona main() para ejecutar ya queesta el primero entonces:

    o PRIORITY 5: calcThread ->main()->NULL

  • 7/21/2019 Threads, hilos en java

    26/47

    ! En T3 comienza readero PRIORITY 5: calcThread->main() ->NULLo PRIORITY 6: reader->NULLo BLOCKED:NULL

    ! En T4 reader se bloque en espera de datos. Y el primero ahoraes calcThread y se ejecuta.o PRIORITY 5: main() -> calcThread ->NULLo PRIORITY 6: NULLo BLOCKED: reader->NULL

    ! Hasta aqu, el proceso es determinista, pero pueden ocurrircomplicaciones que afecten al gestor de threads de igualprioridad. Veamos algunos casos:

    a. Cuando el thread en ejecucin salga del estadorunnable, bien bloquendose o saliendo. En nuestroejemplo esto ocurre cada vez que se bloquea reader.

    b. Cuando un thread que tiene una prioridad ms alta queel thread en ejecucin entra en estado runnable. Ennuestro ejemplo esto ocurre cuando readerentra enaccin o se desbloquea.

    c. Cuando se produce una expiracin en un tiempoarbitrario, Ej: se fija intervalos fijos de 10 veces porsegundo donde hay slo dos threads con prioridad 5:! PRIORITY 5: main() -> calcThread ->NULL! PRIORITY 6: NULL! BLOCKED: reader->NULL

    calcThreades el thread en ejecucin. Entonces,cuando uno de esos intervalos de tiempo cumple seproducen el cambio.! PRIORITY 5: calcThread->main() ->NULL! PRIORITY 6: NULL! BLOCKED: reader->NULLAs, sucesivamente cada decima de segundo.

    ! Si en un momento del programa cambiamos reader a prioridad 5tendremos:

    o PRIORITY 5: reader->calcThread->main()->NULL

  • 7/21/2019 Threads, hilos en java

    27/47

    ! En muchas implementaciones UNIX de Java, el sistema es muydeterminista y el thread esta ejecutndose hasta que finaliza sumtodo run() y sale del estado runnable o hasta que otro threadcon ms alta prioridad entra en estado runnable.

    ! Estados con la misma prioridad no comienzan a ejecutarse y nose dan situaciones del tipo c.

    ! Sin embargo estas situaciones de tipo csi pueden ocurrir enWindows NT o Windows 95. Esto parece que pone en cuestin elsentido de multiplataforma de Java.

    ! Estos diferentes mecanismos de gestin de Java est en relacincon la gestin de threads con que acta el sistema operativo.

    Ejemplo con getPriority y setPriority:public class Fractal extends Applet implements

    Runnable{

    Thread calcThread;

    public void init(){

    Thread current=Thread.currentThread();

    calcThread=new Thread(this);

    calcThread=setPriority(current.getPriority()-1);

    }

    public void start(){

    calcThread.start();

    }

    public void stop(){

    calcThread.stop();

    }

    public void run(){while(sectionsToCalculate){

    doCalc();

    repaint();

    }

    }

    public void paint(Graphics g){

    //pintar cosas basadas en la ltima

    seccin del ltimo fractal calculado

    }

    }

  • 7/21/2019 Threads, hilos en java

    28/47

    ! Supongamos que no asignaramos a calcThread un orden deprioridad ms bajo. En ese caso, el applet debera ejecutarsemediante los mtodos init()y start()con 2 threads enestado NORM_PRIORITY (el del applet y calcThread).

    ! El thread del applet esta en espera a un evento del sistema deventana y el thread calcThreades el nico de los theads enestado runnable que se ejecutar el fractal llamando acontinuacin a repaint().Esto crea un evento necesario paradesbloquear el thread del applet, el cual pasa a ejecutarse.

    ! Como ambos threads tienen la misma prioridad, en muchasplataformas UNIX, el applet debe dejar que finalice calcThread

    aunque este seguir en estado runnable.

    ! Esto puede producir que si el tiempo de ejecucin para calcularel fractal es superior a la respuesta del sistema de ventana enmucha llamadas el mtodo repaint()no tenga efecto ya queel thread del applet no tiene oportunidad de desbloquearse yentrar en ejecucin.

    ! void suspend(): Previene que un thread este ejecutndose

    indefinidamente en el tiempo. Pasa el thread de estado runnablea estado bloquet.

    ! void resume(): Permite que un thread reanude su ejecucindespues de haber sido suspendida.Ejemplo:

    public class Fractal extends Applet implements

    Runnable{

    Thread t;

    public void init(){

    t=new Thread(this);

    }

    public void start(){

    t.start();

    }

    public void stop(){

    t.stop();

    }

  • 7/21/2019 Threads, hilos en java

    29/47

    public void run(){

    while (sectionsToCalculate){

    doCalc();

    repaint();t.suspend();

    }

    }

    public void paint(Graphics g){

    //Draw the section

    t.resume();

    }

    }

    ! La suspensin se produce despus de que cada seccin escalculada, dando la oportunidad al applet a que comience aejecutar la parte grfica.

    ! Hay dos problemas entre cdigo.

    ! Quizs quisiramos permitir control sobre el programa. Ej:que el usuario quisiera cambiar los parmetros grficos atravs de un interfaz. No podemos permitir que el usuario

    realice esto mientras funciona doCalc().

    ! El otro problema es que mientras que el thread de calculo esten estado runnable, el applet est en estado bloqueado y enesta situacin no puede leer ningn nuevo valor que leintroduzcamos.

    ! En estado doCalc(), calculation est en estado runnable y elapplet bloqueado.

    PRIORITY 5: Calculation ->NULLBLOQUET: applet -> NULL

    ! Cuando llamamos a repaint() el applet sale del estadobloqueado y pasa al estado runnable.

    PRIORITY 5: Calculation ->Applet->NULL

    BLOQUET: NULL

    ! Despus de repintar la nueva seccin del fractal se llama a

    resume()dentro de paint. Normalmente resume()manda a

  • 7/21/2019 Threads, hilos en java

    30/47

    calculation de estado bloquet a estado runnable, pero comotodava no ha sido suspendido no tiene efecto esta llamada.

    ! El applet ante esta situacin pasa de nuevo a estado bloqueado

    con lo que no se pintan los cambios realizados.PRIORITY 5: Calculation ->NULLBLOQUET: applet->NULL

    ! Posteriormente se llama a suspend()con lo que calculationtambin se bloquea.

    PRIORITY 5: NULL

    BLOQUET: applet->Calculation->NULL

    ! Esto ocurre porque los dos threads tienen la misma prioridad yambos estn en estado runnable. Veamos una mejor solucin delproblema:

    public class Fractal extends Applet implements

    Runnable{

    Thread t;

    public void start(){

    if (t==null){

    t=new Thread(this);

    t.setPriority(Thread.currentThread().getPriority()-1);

    t.start();

    }

    }

    public void stop(){

    t.suspend();

    }

    public void run(){

    // calculos y repintado doCalc() y repaint()}

    public void paint(Graphics g){

    //Draw the section

    }

    }

    ! Cuando el usuario visita la pagina con el applet, el applet puedesalvar la informacin del fractal ya que slo el thread con msalta prioridad es el responsable de suspender y reanudar elthread calculation.

  • 7/21/2019 Threads, hilos en java

    31/47

    ! Uso de yield():Vimos que lo definimos con que hacia deinterprete entre el thread que actualmente esta ejecutando y elsiguiente. Su verdadera misin es resolver situaciones dondeotro thread con la misma prioridad que el thread que se est

    ejecutando pueda ejecutarse.

    public class YieldApplet extends Applet implements

    Runnable{

    Thread t;

    public void init(){

    t = new Thread(this);

    }

    public void paint(Graphics g){

    t.yield();

    }

    }

    ! Revisemos el uso de mtodo yield sobre el applet fractal:public class Fractal extends Applet implements

    Runnable{

    Thread t;

    public void start(){

    if (t==null){t=new Thread(this);

    t.start();

    }

    }

    public void stop(){

    t.suspend();

    }

    public void run(){

    while (sectionsToCalculate){doCalc();

    repaint();

    t.yield();

    }

    }

    public void paint(Graphics g){

    //Draw the section

    }

    }

  • 7/21/2019 Threads, hilos en java

    32/47

    ! En este caso, el applet resuelve el problema ya que cuando sellama al mtodo repaint(),la mquina virtual cambia el appletcomo thread actual pintando el resultado en paint()y cuando

    vuelve el applet se bloquea de nuevo empezando los clculos denuevo.

    ! Al finalizar el proceso calculation se bloquea. Si volvemos allamar el applet el thread calculation se reanima de nuevo conresumen.

    ! Hemos visto 3 mecanismos de gestin de threads:! Ajustando el orden de prioridades.!

    Mediante los mtodos suspend y resume.! Mediante el mtodo yield.

    ! Los mtodos mediante prioridades permiten mayor flexibilidad.! Cuando los threads necesitan ser parados o arrancados cada

    vez con los mtodos del applet start y stop, merece la penausar suspendy resume.

    ! El mtodo yield es el menos usado de todos ya que debido a lavariabilidad de las plataformas sobre las que se asienta Java, es

    el mtodo que menos garantas ofrece.

    Thread daemon

    ! Hay dos tipos de threads en los sistemas Java: threads deusuario de los que hasta ahora hemos tratado y threads daemon.

    ! Estos ltimos son creados internamente por el API de Java. Lamquina virtual puede crear en nuestro nombre threads daemon.Tienen tambin ordenes de prioridad como los otros y mtodosstart, stop, suspend y resume.

    ! La mquina virtual chequea y analiza si el thread es uso es deusuario o daemon despus de que un thread de usuario hasalido.

    ! A veces, cuando la mquina virtual ve que los threadsremanentes son daemon, sale y finaliza el programa. As, losthreads daemon slo existen para servir a los threads de usuario

    y por tanto no hay razones para que el programa prosiga.

  • 7/21/2019 Threads, hilos en java

    33/47

    ! Los threads cannicos daemon de la mquina virtual es lacoleccin de threads garbage. Esta es una utilidad de threadsque contiene Java para interactuar con el sistema a travs de lamquina virtual.

    ! Mtodo setDaemon(boolean on): El conjunto de threadsson daemon si on = true o de usuario si on = false. Es llamadosolo despus de que el thread objeto ha sido creado y antes deque es arrancado.

    ! Mtodo boolean isDaemon():Retorna true si el thread esdaemon y false si es de usuario.

    Mecanismo de gestin round-robin

    ! El uso de prioridades nos resuelve muchos problemas, pero hayveces que cuando tu tienes threads independientes quenecesitan un mecanismo de gestin del tiempo a pesar de lasplataformas en las que esta ejecutndose.

    ! A veces, pueden haber cientos de threads ejecutndose ypueden necesitar acceder slo de vez en cuando a la CPUestando la mayor parte del tiempo bloqueados.

    ! Si solo tenemos un procesador el mecanismo de gestin solotiene que dar ordenes de prioridad ms bajo a los threads de laCPU respecto de los threads de nuestro programa Java.

    ! Mecanismo de gestin round-robin:A cada thread bajocontrol se le da una cantidad de tiempo fija de ejecucin tal quecuando este tiempo transcurre, otro thread entra en ejecucin,bloquendose el anterior.

    ! Veamos dos razones para su uso:! Hay limitacin de tiempo tal que un gestor es necesario.! El desarrollo de un gestor que ilustre el comportamiento que

    tu necesitas en programacin con muchos threads arbitrarios.

  • 7/21/2019 Threads, hilos en java

    34/47

    Ejemplo:public class SimpleScheduler extends Thread{

    int timeslice;

    public SimpleScheduler(int t){timeslice =t;

    setPriority(Thread.MAX_PRIORITY);

    setDaemon(true);

    }

    public void run(){

    while(true){

    try{

    sleep(timeslice);

    }catch (Exception e){}

    }}

    }

    Usemos la definicin de esta clase como gestor.

    class TestThread extends Thread{

    String id;

    public TestThread(String s){id = s;

    }

    public void run(){

    int i;

    for(i=0;i

  • 7/21/2019 Threads, hilos en java

    35/47

    public class Test{

    public static void main(String args[]){

    new SimpleScheduler(100).start();

    TestThread t1,t2,t3;

    t1 = new TestThread("Thread 1");t1.start();

    t2 = new TestThread("Thread 2");

    t2.start();

    t3 = new TestThread("Thread 3");

    t3.start();

    }

    }

    ! En este programa, hay tres threads con prioridad

    NORM_PRIORITY y el SimpleScheduler con prioridadMAX_PRIORITY. El sistema comienza as:

    PRIORITY 5: t2->t3->t1->NULL

    BLOCKET: SimpleScheduler->NULL

    ! Luego es t1 el que se esta ejecutando y dice "thread 1".Supongamos, que finaliza la espera de SimpleScheduler y sedespierta pasando a estado runnable al tener una prioridad msalta, entonces:

    PRIORITY 5: t2->t3->t1->NULLPRIORITY 10: SimpleScheduler->NULL

    ! Se ejecuta la espera y vuelve a bloquearse ejecutndose t2 acontinuacin:

    PRIORITY 5: t3->t1->t2->NULL

    BLOCKET: SimpleScheduler->NULL

    ! Este gestor SimpleScheduler podemos hacerlo ms elaborado

    incluyendo tres niveles de prioridad. Ejemplo:public class CPUScheduler extends Thread{private int timeslice;

    // clase lista circular

    // contiene los mtodos

    //insert= inserta un elemento a la lista

    //delete= elimina un elemento de la lista

    //getNext= pasa al siguiente elemento de la

    lista.

    private CircularList threads;

  • 7/21/2019 Threads, hilos en java

    36/47

    public CPUScheduler(int t){

    threads = new CircularList;

    timeslice t;

    }

    public addThread(Thread t){

    threads.insert(t);

    t.setPriority(2);

    }

    public removeThread(Thread t){

    t.setPriority(5);

    threads.delete(t);

    }

    public void run(){

    Thread current;

    current.setPriority(6);

    while(true){

    current = (Thread) thread.getNext();

    if(current ==null) return;

    current.setPriority(4);

    try{

    Thread.sleep(timeslice);}catch (InterruptedException ie){}

    current.setPriority(2);

    }

    }

    }

  • 7/21/2019 Threads, hilos en java

    37/47

    Usemos la definicin de esta clase como gestor.

    class TestThread extends Thread{

    String id;

    public TestThread(String s){

    id = s;

    }

    public void run(){

    int i;

    for(i=0;it3->t1->NULL

    PRIORITY 6: CPUScheduler->NULL

    ! El thread de mayor prioridad es CPUScreduler que es el que seejecuta con el mtodo run(). Pasa al siguiente thread t1 y asignaprioridad 4.

    PRIORITY 2: t2->t3->NULL

    PRIORITY 4: t1->NULL

    PRIORITY 6: CPUScheduler->NULL

  • 7/21/2019 Threads, hilos en java

    38/47

    ! CPUScheduler esta en estado runnable pero bloqueado lo quepermite a t1 ejecutarse.

    PRIORITY 2: t2->t3->NULL

    PRIORITY 4: t1->NULL

    BLOQUET: CPUScheduler->NULL

    ! Cuando CPUScheduler despierta pasa t1 a prioridad 2 y laprioridad de t2 a 4

    PRIORITY 2: t3->t1->NULL

    PRIORITY 4: t2->NULL

    PRIORITY 6: CPUScheduler->NULL

    ! Y el ciclo continua sucesivamente.

    1.Sin embargo la clase CPUScheduler todava tiene problemasde sincronizacin. Para resolverlo, modificaremos dos desus mtodos.

    2. Tambin autosalvaremos la prioridad del thread.

    3. Qu sucede si dos threads intentan crear unCPUScheduler?. Para resolver esta situacinnecesitamos inicializar la clase. Podemos usar

    una variable esttica en la clase paradiferenciar las clases.

    ! Se introduce mtodo de sincronizacin para elacceso a la variable esttica y una excepcin enel constructor.

    4. Podemos cambiar el gestor de forma que se quedeen modo de espera cuando no queden ms threadsque gestionar.

    !

    En el constructor hemos establecido que elthread sea daemon.! Tambin hemos establecido que si un thread no

    esta en la lista nosotros esperamos con wait()hasta que uno est disponible. Con notify()notificamos que el thread estaba en espera y lacondicin se ha cumplido.

  • 7/21/2019 Threads, hilos en java

    39/47

    public class CPUScheduler extends Thread{

    // clase lista circular

    // contiene los mtodos

    //insert= inserta un elemento a la lista

    //delete= elimina un elemento de la lista//getNext= pasa al siguiente elemento de la

    lista.

    private CircularList threads;

    private Thread current; //1

    private int timeslice;

    private static boolean initialized = false;//3private boolean needThreads; //4

    private synchronized static boolean

    isInitialized(){ //3if (initialized) return true;initialized = true;return false;

    }

    public CPUScheduler(int t){

    if (isInitialized()) //3

    throw new SecurityException("Alreadyinitialized");

    threads = new CircularList();

    timeslice t;

    setDaemon(true); //4

    }

    public synchronized void addThread(Thread t){

    t.setPriority(2);

    threads.insert(t);

    if (needThreads){ //4needThreads = false;notify();

    }

    }

  • 7/21/2019 Threads, hilos en java

    40/47

    public void removeThread(Thread t){

    try{ //2t.setPriority(5);

    }catch(Exception e){}

    threads.delete(t);syncronized(this){ //1if(currect ==t) current =null;

    }

    }

    public synchronized void run(){

    current.setPriority(6);

    while(true){

    current = (Thread) thread.getNext();

    while(current == null){needThreads=true;try{

    wait();}catch (Exception e){}current=(Thread)threads.getNext();

    }

    try{ //2current.setPriority(4);

    }catch(Exception e){removeThread(current);continue;

    }

    try{

    sleep(timeslice);

    }catch (InterruptedException ie){}if(currect !=null) {

    try{ //2current.setPriority(2);

    }catch(Exception e){removeThread(current);

    }}

    }

    }

    }

  • 7/21/2019 Threads, hilos en java

    41/47

    ! En este punto, tenemos un gesto robusto, donde hemossincronizado todas las variables de estado internascorrectamente.

    ! Tambin nos hemos asegurado de que no nos aparezcanexcepciones ante los cambios externos que hagamos.

    PROBLEMAS:! Sin embargo, puede suceder que el thread que en ese momento

    esta ejecutndose de repente entra en estado de bloqueo.Supongamos el siguiente estado:

    PRIORITY 2: t3->t1->NULL

    PRIORITY 4: t2->NULL

    BLOQUET: CPUScheduler->NULL

    ! Si t2 se bloquea de repente entonces:PRIORITY 2: t3->t1->NULL

    PRIORITY 4: NULL

    BLOQUET: t2->CPUScheduler->NULL

    ! Esto significa que t3 comienza a ejecutarse en prioridad 2.Cuando la CPUScheduler despierta establece t2 con prioridad 2

    y pasa t3 a prioridad 4 cuando CPUScheduler tiene el retardocon sleep.PRIORITY 2: t1->NULL

    PRIORITY 4: t3->NULL

    BLOQUET: t2->CPUScheduler->NULL

    ! Todo esta bien, pero cuando avanza el proceso, llegara unmomento que t2 pase a prioridad 4. En nuestro gestor no hemosestablecido un camino para decirle que t2 est en estado

    bloqueado.

    ! Una forma de resolver esto es generar una clase de forma quecuando el thread de prioridad 4 se ha bloqueado necesitamos unthread de prioridad 3. As, cuando un thread de prioridad 3 seest ejecutando significa que el thread de prioridad 4 estbloqueado y notifica a la prioridad 6 que un nuevo thread deprioridad 4 ha de ser seleccionado.

    ! Ha este thread de prioridad 3 le llamaremos "ThreadNotifier"

  • 7/21/2019 Threads, hilos en java

    42/47

    ! Este nuevo problema, plantea nuevos dilemas, ya que puedesuceder que se de repente se bloquee uno o todos.

    ! De alguna forma debemos decirle a la CPUSchreduler que si

    todos los threads estan bloqueados pase a un estado de espera.Tambin que si algun thread se desbloquea pueda despertarse yseguir gestionando el problema. Para ello generaremos la claseCPUSchedulerNode.

    class CPUSchedulerNode{Thread thread;

    boolean blocked;

    CPUSchedulerNode(Thread t){thread = t;

    blocket = false;}

    public boolean equals(Object o){if (thread ==o) return true;return false;

    }}

    class ThreadNotifier extends Thread{CPUScheduler c;

    public ThreadNotifier(CPUScheduler c){setPriority(3);this.c = c;

    }public void run(){

    boolean done=false;while (!done){

    c.wakeup();}

    }}

  • 7/21/2019 Threads, hilos en java

    43/47

    public class CPUScheduler extends Thread{

    private CircularList threads;

    private CPUSchedulerNode current;

    private int nThreads = 0;private ThreadNotifier notification;private Thread scheduler;

    private int timeslice;

    private static boolean initialized = false;

    private boolean needThreads = false;

    private synchronized static boolean

    isInitialized(){

    if (initialized) return true;initialized = true;

    return false;

    }

    public CPUScheduler(int t){

    if (isInitialized()) //3

    throw new SecurityException("Already

    initialized");

    threads = new CircularList();

    timeslice t;

    nThreads = 0;

    }

    public synchronized void addThread(Thread t){

    CPUSchedulerNode n = newCPUSchedulerNode(t);t.setPriority(2);

    threads.insert(n);nThreads++;

    if (needThreads){ //4

    needThreads = false;

    notify();

    }

    }

  • 7/21/2019 Threads, hilos en java

    44/47

    public synchronized void removeThread(Thread

    t){

    // locate mtodo de listaCircular// delete mtodo de listaCircular

    Object n=thread.locate(t);

    threads.delete(n);

    if(currect ==t) current =null;

    nThreads--;

    }

    public synchronized void wakeup(){notify();

    }

    public void startScheduler(){notification = new ThreadNotifier(this);notification.setDaemon(true);notification.start();scheduler = new Thread(this);scheduler.setDaemon(true);scheduler.start();

    }

    public void stopScheduler(){scheduler.stop();notification.stop();

    }

    public synchronized void run(){

    long now,then;int nBloqued = 0;Thread.currentThread().setPriority(6);

    now = System.currentTimeMillis();

    while(true){

    current = (CPUSchedulerNode)

    thread.getNext();

    while(current == null){

    needThreads=true;

    try{

    wait();

    }catch (Exception e){}current=(CPUSchedulerNode)

  • 7/21/2019 Threads, hilos en java

    45/47

    threads.getNext();

    }

    try{

    current.Thread.setPriority(4);}catch(Exception e){

    removeThread(current.Thread);

    continue;

    }

    then = now;

    if(nBloqued==nThreads)notification.suspend();else notification.resume();try{

    wait(timeslice);}catch (InterruptedException ie){}

    now =System.currentTimeMillis();

    if(currect !=null) {

    try{

    current.Thread.setPriority(2);

    if (now-then

  • 7/21/2019 Threads, hilos en java

    46/47

    APENDICE: Cdigo de la lista Circular

    public class CircularListNode{Object o;

    CircularListNode next;

    CircularListNode prev;

    }

    public class CircularList{

    private CircularListNode current;

    public synchronized void insert(Object o){

    CircularListNode tn = new

    CircularListNode();

    tn.o=o;

    if (current = null){

    tn.next = tn.prev = tn;

    current = tn;

    }else{

    tn.next = current;

    tn.prev = current.prev;

    current.prev.next = tn;current.prev = tn;

    }

    }

    public synchronized void delete(Object o){

    CircularListNode p = find(o);

    CircularListNode next = p.next;

    CircularListNode prev = p.prev;

    if (p == p.next){ // ultimo elemento

    current = null;

    return;

    }

    prev.next = next;

    next.prev = prev;

    if (current == p) current =next;

    }

  • 7/21/2019 Threads, hilos en java

    47/47

    private CircularListNode find(Object o){

    CircularListNode p = current;

    if (p == null)throw new IllegalArgumentException();

    do{

    if(p.o == o) return p;

    p = p.next;

    }while p != current);

    throw new IllegalArgumentException();

    }

    public synchronized Object locate(Object o){

    CircularListNode p = current;do{

    if (p.o.equal(o)) return p.o;

    p = p.next;

    }while (p != current);

    throw new Illegal ArgumentException();

    }

    public synchronized Object getNext(){

    if (current == null) return null;current = current.next;

    return current.o;

    }

    }