logbitup.gif (360 bytes)

 Curso JAVA 
 Unidad 5: "Threads y multitarea"

logbitdn.gif (787 bytes)

  www.bit.es - Calendario de cursos - Solicitud de información

Curso Java
Curso Analista Programador entorno Java

Objetivos de la Unidad:  


1.- Programación modular clásica  
 

2.- Programación con Threads ("Hilos")  
 

3.- Conversión de una llamada a función normal a una multithread

  •  

    Supongamos que disponemos de una función denominada servicio tal como:

        void servicio(String s, int a, boolean b)
      {
          <código de servicio>
      }
     

    Una llamada a la función servicio sería:
     

    ...
    servicio("Hola", 5, true);
    ...
     

    En este caso la línea siguiente a la llamada no se ejecutará hasta que servicio devuelva el control.

    En programación multithread podríamos escribir lo siguiente:
     

    ...
    new Servicio("Hola", 5, true);
    ...


    En este caso la línea siguiente a la llamada se ejecutará independientemente (en paralelo) con el thread de Servicio.
     

    La técnica para pasar de la primera forma a la segunda consiste en mapear el constructor de Thread con los mismos parámetros, de modo que la clase Servicio quedaría como sigue:

     

    class Servicio extends Thread
    {
        String s;
        int a;
        boolean b;

        Servicio(String s, int a, boolean b)
        {
            this.s = s;
            this.a = a;
            this.b = b;
            start();     // el Thread se autoarranca
        }

        public void run()
        {
            try
            {
                <código de servicio>
            }
            catch(InterruptedException e) {}
        }
    }
     
     

    Obsérvese que run accedería a las variables miembro directamente de modo equivalente que la función servicio en que estos datos llegan como parámetros.

    El método start es al comando java (ó jview) lo que run es a main

    La llamada a una función en modo clásico se puede ver como un caso de particular en el modelo multithreaded. Basta con indicar que el Thread del programa "llamante" se bloquee hasta que el "llamdado" no termine. Ello se consigue utilizando el método join:
     
    ...
    new Servicio("Hola", 5, true).join();
    ...

    El método join es utilizado en aquellos casos en que se lanzan varios threads y no se quiere continuar hasta que acaben todos ellos:

        Thread t1 = new ...
        Thread t2 = new ...
        Thread t3 = new ...

        t1.join();
        t2.join();
        t3.join();
     

    En este caso hasta que no terminen los tres Threads t1, t2 y t3 el programa no pasará la zona de joins. En cierto modo actúa como un elemento transaccional (se componen en lógica "AND").
     
     

     

  • 4.- Herencia de Thread versus implementación de Runnable  
     

      

     

     

     

    5.- Ciclo de vida de un Thread.  
     

       
     

                ...
          Thread.currentThread().sleep(2000); // el programa se detiene durante 2 segundos
          ...

    6. Sincronización  

     

     7.- Ejemplo  
     

  • //
    // PC.java
    //
    // Problema del productor-consumidor
    //
     

    /// Recurso accedido por p y c

    class Q
    {
        int n;
        boolean valueSet = false;

        synchronized int get()
        {
            if (!valueSet)
                try {wait();} catch (InterruptedException e){}

            System.out.println("Obtenido: " + n);
            valueSet = false;
            notify();
            return n;
        }

        synchronized void put(int n)
        {
            if (valueSet)
                try {wait();} catch (InterruptedException e){}

            this.n = n;
            valueSet = true;
            System.out.println("Colocado: " + n); notify();
        }
    }
     

    Productor implements Runnable
    {
        Q q;
        Thread t;

        Productor(Q q)
        {
            this.q = q; t = new Thread(this, "Productor");
            t.start();
        }
     

        public void run()
        {
            int i = 0;
            while(true)
            {
                try {t.sleep(1500);} catch(Exception e){}
                q.put(i++);
            }
        }
    }

     

    Consumidor implements Runnable
    {
        Q q;
        Thread t;

        Consumidor(Q q)
           
    {
            this.q = q; t = new Thread(this, "Consumidor");
            t.start();
        }
     

        public void run()
        {
            while(true)
            {
                try {t.sleep(1000);} catch(Exception e){}
                q.get();
            }
         }
    }
     

    PC
    {
        public static void main(String args[])
           
    {
            Q q = new Q();
            new Productor(q);
            new Consumidor(q);
        }
    }

  • 8.- Miscelánea


    Unidad anterior - Unidad siguiente