martes 5 de mayo de 2009

Empezando con concurrencia en Java

java Este post formara parte de varios que escribiré en los próximos días y seguramente con el resumen final que elabore para esta materia(Paradigmas de Programación).
Son las primeras pruebas con programación concurrente o multihilos en Java, si buscas todos los post ingresados en la etiqueta Java de mi blog encontraras algunos post interesantes de practicas en consola y en el editor visual de Eclipse.
Vuelvo a repetir que esto es lo primero que hago con esta perspectiva de programación.
Se trata de un programa muy básico en consola donde se desarrollan tres hilos con una clase que hereda de Thread y que se ejecutan en paralelo(Paralelismo de Software) es bastante corta pero es de gran ayuda para comprender de que se trata esto de la concurrencia, cada vez que ejecutamos el programa podemos ver como da distintos resultados sin cambiar nada del código, esto es en parte por que genero un numero al azar en cada Thread pero tambien por que algunos hilos se ejecutan antes que otros aunque sean llamados en tiempos distintos, esto depende de la disponibilidad de recursos de la maquina virtual de Java, una vez que hallan copiado el post(si es que tengo el agrado de que me visite un estudiante de Java) recomiendo ejecutar repetidamente el programa para ver los resultados.
Los objetos concurrentes deben ser instanciados a partir de una clase que herede de Thread o que implemente la interfaz Runnable, para los casos donde necesitemos extender la clase de otra como por ejemplo un JFrame para aplicaciones visuales.
El uso de la interfaz requiere tratar a los objetos de manera distinta en su inicialización. Pero por ahora como se trata de un ejemplo por consola solo usare la clase Thread.
Estas clases se encuentran disponibles en Java sin tener que importar ningún paquete especial. En este caso tampoco haba que usar una librería para la lectura de datos por consola ya que no se lee ningún dato.
Vamos al ejemplo: MiThread.java:

public class MiThread extends Thread {
private int numero;
private String cadena;

public void run()
{
numero = (int)(Math.random()*100);
System.out.println(cadena+"--->"+numero);
}
public int getNumero()
{
return numero;
}
public void setCadena(String cadena)
{
this.cadena = cadena;
}
}

Esta es la estructura clásica de una clase extendida de Thread, la única diferencia es que debe tener una funcion llamada run() la cual es llamada por la estructura de Thread en la funcion start(), además no es necesario especificar un constructor.
Lo que realiza esta clase cuando es instanciada es crear un objeto MiThread con dos atributos un entero llamado numero y una cadena de caracteres llamada cadena, las funciones son run que especifica las acciones del Thread cuando es ejecutado y donde se pueden pasar mensajes a otras funciones del Thread o acceder a variables, en el ejemplo run() accede setea numero y lee cadena.
Para ver mejor el funcionamiento tenemos que crear otra clase principal que haga uso de esta clase MiThread:
Main.java:

public class Main {
public static void main(String []arg) throws InterruptedException
{ //Declaracion de los tres hilos
MiThread m1, m2, m3;
m1 = new MiThread();
m2 = new MiThread();
m3 = new MiThread();
//Enviar el nombre al hilo
m1.setCadena("Hilo 1");
m2.setCadena("Hilo 2");
m3.setCadena("Hilo 3");
//Arrancar los tres hilos
m1.start();
m2.start();
m3.start();
//Puede haber algun error
try{
//Espera a que finalizen los hilos
m1.join();
m2.join();
m3.join();
}
catch (InterruptedException e) {
System.out.println("Hubo un Error en algun lado");
}
//Obtener el valor de los numeros
System.out.println("La suma es: "+(m1.getNumero()+m2.getNumero()+m3.getNumero()));
}
}
La clase Main lo que hace es ser el centro de la aplicación como cualquier clase típica con void main, adentro de esa clase se instancian los tres objetos MiThread. Una vez que están instanciados tenemos reservados los espacios de memoria necesarios para cada objeto por lo que podemos acceder a los métodos y lo que hacemos es asignarle un nombre a cada uno seteando el atributo cadena.
Luego pasamos a la parte nueva que es llamar a la funcion start, esta funcion es de Thread que internamente llama a run() pero que forma parte de algo mas “grande” no se debe llamar nunca a la funcion run() simplemente.
Cuando llamamos a start es cuando comienza la concurrencia, en ese momento el programa se esta ejecutando en cuatro hilos simultáneos emulados por Paralelismo de Software a no ser que cuentes con una CPU con 4 procesadores, cosa que no creo.
Luego le decimos a los tres hilos que esperaremos a que se terminen de ejecutar con la funcion join(), en este momento se pueden producir errores que es necesario capturar con un try catch, o con el throws InterruptedException en la declaración de la clase.
Se pueden utilizar los dos métodos o uno solo, pero si no usamos ninguno el compilador no nos dejara ejecutar el programa.
Luego que los tres objetos han terminado y nos mostraron por pantalla sus distintas informaciones volvemos a acceder a los atributos del objeto por la funcion correspondiente para saber la suma de sus “numeros” por que los objetos no fueron eliminados aunque ya no se están ejecutando.
Cuando lo ejecuten verán que no siempre se cumple que la cadena1 salga en primero orden, a mi ha pasado que el tercer Thread es mas rápido que los otros dos, pero como dije esto depende de la evaluación que haga la maquina virtual de los hilos, así podemos comprobar la concurrencia que se da en este ejemplo.
Bueno la verdad que me esmere mucho esta vez, espero que le sirva a alguien, seguramente en pocos días estaré escribiendo algo mas largo con interfaz visual y concurrencia.
Saludos.

1 comentarios:

Jåçkÿ dijo...

ami si m sirvio ^^