46. TEMA EXTRA (La Concurrencia)

Este es un tema extra, quiere decir, que no deberia estar en el Mini-Curso de Java. Pero me ha parecido interesante introducirlo al final de todos los temas. 

El siguiente tema trata sobre la programacion concurrente. La concurrencia trata sobre todo de tener varias tareas en concurrencia, es decir, ejecutandose simultaneamente. Por ejemplo, pueden haber dos clases que se esten ejecutando simultaneamente, o cuando haces dos descargas a la vez, dichas descargas se estan ejecutando simultaneamente hasta que lleguen las dos al 100%.

 

¿Que utilizamos para hacer estas tareas de simultanuidad?. Pues utilizamos los "Thread" o los "Runnable". Esto quiere decir que un Thread es una tarea para la ejecucion de una aplicacion o programa y lo mismo para un Runnable. La diferencia de los dos, es que el Thread se hereda y el Runnable se implementa. ¿Y porque hacen los dos lo mismo?, pues cuando heredamos en una clase, solo se puede heredar una vez, pues, si heredamos de "JFrame" ya no podemos heredar de "Thread" y necesitariamos implementar de "Runnable".

Por ejemplo, imagina que heredamos en la clase de "Thread", quedaria asi:

 

public class Ejemplo extends Thread{

 

}

 

Sin embargo, ahora si heredamos de JFrame, ya no podemos heredar de Thread, por eso utilizaremos el Runnable, quedaria asi:

 

public class Ejemplo extends JFrame implements Runnable{

 

}

 

En los dos casos estariamos haciendo lo mismo.

Ahora imaginate que queremos que un Thread nos escriba una frase de cada tarea y que la repita 20 veces cada tarea, pero queremos que lo haga simultaneamente, se turnen para que las dos tareas cumplan su cometido hasta que terminen. Vamos a hacer un ejemplo para que lo veamos mas claro.

Creamos una clase que se llama "EjemploConcurrencia" y lo hacemos de la siguiente manera:

 

public class EjemploConcurrencia extends Thread{
    
    private String dato;
    
    public EjemploConcurrencia(String dato){
        this.dato = dato;
    }
    
    public void run(){
        for(int i=1; i<=50; i++){
            System.out.println(i+" - trabajando "+dato);
        }
    }
    
}
 
Hemos heredado de "Thread" y hemos escrito su metodo para el funcionamiento de este que es el metodo "run()". Ahora creamos otra clase llamada "Principal" con su metodo "main", asi:
 
 
public class Principal {
 
    public static void main(String[]args){
 
        EjemploConcurrencia ec1 = new EjemploConcurrencia("Tarea 1 ");
        EjemploConcurrencia ec2 = new EjemploConcurrencia("Tarea 2 ");
 
        ec1.start();
        ec2.start();
 
    }
}
 
Inicializamos dos instancias de la clase con dos tareas diferentes y le indicamos con el metodo "start()" que inicialize las tareas del "Thread".
El resultado sera el siguiente:
 
1 - trabajando Tarea 2 
2 - trabajando Tarea 2 
3 - trabajando Tarea 2 
4 - trabajando Tarea 2 
5 - trabajando Tarea 2 
6 - trabajando Tarea 2 
7 - trabajando Tarea 2 
8 - trabajando Tarea 2 
9 - trabajando Tarea 2 
10 - trabajando Tarea 2 
11 - trabajando Tarea 2 
12 - trabajando Tarea 2 
13 - trabajando Tarea 2 
14 - trabajando Tarea 2 
15 - trabajando Tarea 2 
16 - trabajando Tarea 2 
17 - trabajando Tarea 2 
18 - trabajando Tarea 2 
19 - trabajando Tarea 2 
20 - trabajando Tarea 2 
1 - trabajando Tarea 1 
2 - trabajando Tarea 1 
3 - trabajando Tarea 1 
4 - trabajando Tarea 1 
5 - trabajando Tarea 1 
6 - trabajando Tarea 1 
7 - trabajando Tarea 1 
8 - trabajando Tarea 1 
9 - trabajando Tarea 1 
10 - trabajando Tarea 1 
11 - trabajando Tarea 1 
12 - trabajando Tarea 1 
13 - trabajando Tarea 1 
14 - trabajando Tarea 1 
15 - trabajando Tarea 1 
16 - trabajando Tarea 1 
17 - trabajando Tarea 1 
18 - trabajando Tarea 1 
19 - trabajando Tarea 1 
20 - trabajando Tarea 1  
 
Pero ojo, no precisamente en este orden, puede iniciar primero la tarea2 y despues la tarea1, como pude hacerse a la inversa, no hay una prioridad.
Ahora haremos el mismo ejercicio, pero vamos a añadir el metodo "sleep()", pues con el haremos que la tarea duerma X milisegundos antes de que reanude otra vez la tarea, esto requiere que nos ayudemos de los try/catch (Excepciones), aqui el ejemplo:
En la clase "EjemploConcurrencia" añade esto:
 
public class EjemploConcurrencia extends Thread{
 
    private String dato;
 
    public EjemploConcurrencia(String dato){
        this.dato = dato;
    }
 
    public void run(){
        try{
            for(int i=1; i<=20; i++){
                System.out.println(i+" - trabajando "+dato);
                Thread.sleep(1000);
            }
        }catch(Exception ex){ex.printStackTrace();}
    }
 
}
 
 
Ahora intenta ejecutar el programa otra vez. El resultado sera el siguiente:
 
1 - trabajando Tarea 1 
1 - trabajando Tarea 2 
2 - trabajando Tarea 2 
2 - trabajando Tarea 1 
3 - trabajando Tarea 2 
3 - trabajando Tarea 1 
4 - trabajando Tarea 2 
4 - trabajando Tarea 1 
5 - trabajando Tarea 1 
5 - trabajando Tarea 2 
6 - trabajando Tarea 1 
6 - trabajando Tarea 2 
7 - trabajando Tarea 1 
7 - trabajando Tarea 2 
8 - trabajando Tarea 2 
8 - trabajando Tarea 1 
9 - trabajando Tarea 1 
9 - trabajando Tarea 2 
10 - trabajando Tarea 1 
10 - trabajando Tarea 2 
11 - trabajando Tarea 2 
11 - trabajando Tarea 1 
12 - trabajando Tarea 1 
12 - trabajando Tarea 2 
13 - trabajando Tarea 1 
13 - trabajando Tarea 2 
14 - trabajando Tarea 1 
14 - trabajando Tarea 2 
15 - trabajando Tarea 2 
15 - trabajando Tarea 1 
16 - trabajando Tarea 2 
16 - trabajando Tarea 1 
17 - trabajando Tarea 1 
17 - trabajando Tarea 2 
18 - trabajando Tarea 1 
18 - trabajando Tarea 2 
19 - trabajando Tarea 2 
19 - trabajando Tarea 1 
20 - trabajando Tarea 2 
20 - trabajando Tarea 1 

 

Ahora, vamos a hacer un ejercicio en el cual en vez de "Thread" utilizaremos "Runnable" y lo haremos con el siguiente ejercicio:

En la clase "EjercicioConcurrencia", lo siguiente:

 

public class EjercicioConcurrencia implements Runnable{
 
    private int num = 7;
    private int sum = 0;
 
    public void run(){
        try{
            for(int i=1; i<=10; i++){
                sum = num*i;
                System.out.println(num+" x "+i+" = "+sum);
                Thread.sleep(1500);
            }
        }catch(Exception ex){ex.printStackTrace();}
    }
 
}

 

Con el metodo "sleep()" le indicamos en formato milisegundos, en este caso seria un segundo y medio, el tiempo que dormira la tarea hasta que esta se reanude. Y ahora con la clase "Principal" escribimos lo siguiente:

 

public class Principal {
 
    public static void main(String[]args){
 
        EjemploConcurrencia ec1 = new EjemploConcurrencia();
        Thread th = new Thread(ec1);
 
        th.start();
 
 
    }
}
 
Ejecuta el codigo y mira lo que ocurre.
Igualmente que con el Thread y el resultado en la pantalla de consola sera este:
 
7 x 1 = 7
7 x 2 = 14
7 x 3 = 21
7 x 4 = 28
7 x 5 = 35
7 x 6 = 42
7 x 7 = 49
7 x 8 = 56
7 x 9 = 63
7 x 10 = 70
 
Bien, el tema de la concurrencia, es mas extensa, porque tendriamos mas metodos como "notify()", "wait()", tema de los monitores y sincorinizacion en clases, pero en este mini-curso no lo daremos. Con esto es mas que suficiente para que te introduzcas en este mundo apasionante.

 

Contacto

ProgramandoJava cabillo@hotmail.es