DPO3_U2_A2_JORP

download DPO3_U2_A2_JORP

of 18

description

POO

Transcript of DPO3_U2_A2_JORP

Multiprocesos en Java: Hilos(Threads)

El flujo mltiple de ejecucin de programas permite que se estn realizando diferentes tareas al mismo tiempo en un programa, es decir, que las tareas se ejecuten de forma paralela, para ello Java utiliza unos elementos llamados hilos (thread).Cadahilorealiza una tarea en especfico, al tener varios hilos ejecutndose, se tendrn varias tareas corriendo en el mismo programa. Lo que permitir que en el mismo programa se estn realizando diferentes actividades al mismo tiempo.

En Java, as como en cualquier lenguaje de programacin, la principal estructura de ejecucin de instrucciones es la estructura secuencial, en la que cada comando, cada lnea, cada instruccin se ejecuta una despus de otra. El cdigo se ejecuta de arriba hacia abajo y cada lnea es ejecutada segn el orden en que haya sido escrita por el programador.

El diagrama de flujo siguiente lo ejemplifica:

En ocasiones puede que el usuario necesite llevar a cabo 2 o ms procesos a la vez. Supongamos que queremos realizar 3 procesos al mismo tiempo, como lo vemos en este modelo:

Esto es completamente IMPOSIBLE ya que el procesador de una computadora no es capaz de realizar estas funciones. Sin embargo existen alternativas, como los Hilos o Threads.

Si vemos el diagrama de arriba, podemos identificar 3 hilos: Proceso 1, Proceso 2 y Proceso 3. Pero, ya hemos dicho que esto no es posible de la forma como lo hemos presentado en el diagrama de flujo.

Si intentamos utilizar una estructura secuencial para ejecutar 3 procesos, obtendremos el siguiente resultado:

Existe una serie de inconvenientes con esto: el proceso1 slo se ejecutar cuando haya terminado el proceso 2. El proceso 3 se empezar a ejecutar cuando haya terminado el proceso 1 y 2.

Con los hilos o threads, podemos obtener una ejecucin lo ms cercana posible al modelo de los 3 hilos que present arriba. Los threads son estructuras secuenciales que combinan las lneas de 2 o ms procesos en un solo proceso.

Si lo expresamos con un diagrama de flujo se vera de la siguiente forma:

Los comandos en azul pertenecen al proceso 1, los comandos en rojo son del proceso 2 y el rojo del proceso 3.

La forma como se ejecutan los procesos es completamente aleatoria. Puede que se inicie la ejecucin con el proceso 2, luego el 2, luego el 3, luego el 1 y as sucesivamente.

No siguen un orden especfico. Esto permite que los 3 vallan corriendo al mismo tiempo, dando como resultado algo bastante parecido a aquel modelo que ya hemos dicho que no es posible obtener con los procesadores de nuestras computadoras.

Mientras que los programas de flujo nico pueden realizar su tarea ejecutando las sub-tareas secuencialmente, un programa multitarea permite que cada tarea comience y termine tan pronto como sea posible. Este comportamiento presenta una mejor respuesta a la entrada en tiempo real.Los hilos de ejecucin en Java estn implementados en la clasethread, que forma parte del paquetejava.lang.

Cada hilo (thread) tiene un principio, un flujo de ejecucin y un fin definidos, pero no es una entidad independiente sino que debe ejecutarse en el contexto de un programa (Joyanes, 2002).Veamos cmo funcionan los Threads con una aplicacin en Java. Vamos a Netbeans y creamos un proyecto llamadoThreads. Insertamos un JFrame y le colocamos un botn con el que iniciaremos la ejecucin se los Threads.

Ahora vamos al cdigo y declaramos 3 variables tipo Thread.

Ahora vamos a programar el botn que colocamos en el JFRame.

Dentro del cdigo del botn iniciaremos los threads. Colocamos lo siguiente:

Aqu Netbeans marca 3 errores con la inicializacin de los threads. Esto se debe a que necesitamos implementar la interfaz Runnable en la Clase de nuestra JFrame.Lo corregimos dando clic en el cono de la izquierda en nuestra declaracin de la clase public class ThreadsG extends javax.swing.JFrame { para corregir el error. Nos aparecer la opcin Implement all abstract methods, quedara de la siguiente manera: public class ThreadsG extends javax.swing.JFrame implements Runnable{Para ver como se ejecutan los threads, veremos una carrera de 3 procesos. Primero declararemos 3 variables, c1, c2 y c3. Sern del tipo entero y las inicializaremos en 0.

Luego introduciremos los siguientes mtodos:

public void corredor1() {c1++;}

public void corredor2() {c2++;}

public void corredor3() {c3++;}

Estos mtodos lo que harn es que le agregarn una unidad a cada una de las variables, es decir, c1, c2 y c3. Ahora nos dirigimos al final del programa, donde est el mtodopublic void run().

All colocamos lo siguiente:

Thread ct = Thread.currentThread();

while (ct == hilo1) {

corredor1();

System.out.println("Corredor 1: " + c1);

}

while (ct == hilo2) {

corredor2();

System.out.println("Corredor 2: " + c2);

}

while (ct == hilo3) {

corredor3();

System.out.println("Corredor 3: " + c3);

}/Esto funciona de la siguiente manera:

La variablectadoptar el valor del CurrenThread, es decir, el hilo que se est ejecutando en determinado instante.

Mientras ese hilo que se est ejecutando sea elhilo1, se ejecutar la funcincorredor1que es la encargada de aumentar la variablec1.La funcin System.out.println(Corredor 1: + c1);imprime el valor de c1 en la parte inferior de Netbeans IDE.

Se repite el mismo proceso para los otros 2 hilos. Lo que queremos darnos cuenta es como Java ejecuta el cdigo. Lo hemos colocado uno debajo del otro, como una secuencia, pero al ejecutar el programa y presionar el botn nos damos cuenta de que no es una secuencia.

Cuando ejecutamos el programa obtenemos lo siguiente:

/Como podemos observar, el proceso inici ejecutndose con el mtodo 1 (corredor1) pero al llegar a la lnea 493 se volvi aleatorio, es decir, el proceso 2 y 3 empezaron a ejecutarse a medida que el proceso 1 tambin se ejecutaba.

Si detenemos el programa y empezamos una nueva ejecucin obtendremos otro tipo de comportamiento. /Ahora el primer proceso en ejecutarse fue el proceso 1, luego el 3 y despus el 2. Es probable que cada vez que ejecutemos el programa obtendremos resultados diferentes. Podemos observar que no es necesario esperar que el proceso 1 se termine de ejecutar para empezar con el 2 y el 3, sino que los 3 se ejecutarn en manera conjunta.

Al final le hice unas modificaciones al cdigo para obtener los resultados en una interfaz grfica utilizando jFrame, el sistema se detiene cuando cualquiera de los Corredores llega a 500 para este ejemplo.

El cdigo es el siguiente:

/*

* Jos Luis Rubio Padilla

* Manejo de Hilos en JAVA

*

*/

package threads;

/**

*

* @author jlrubio

*/

public class ThreadsG extends javax.swing.JFrame implements Runnable{

//Estas variables sirven para dar nombre a lo hilos y

//se imprimirn cada vez que los hilos estn en ejecucin.

Thread hilo1;

Thread hilo2;

Thread hilo3;

int c1=0, c2=0, c3=0; //Inicializa las cariables que se utilizaran para ejemplificar los hilos

String texto1="", texto2="", texto3="";

//Estos metodos incrementan la variable en uno, se ejectaran en hilos diferentes

public void corredor1() {

c1++;

}

public void corredor2() {

c2++;

}

public void corredor3() {

c3++;

}

/**

* Creates new form ThreadsG

*/

public ThreadsG() {

initComponents();

}

/**

*/

@SuppressWarnings("unchecked")

//

private void initComponents() {

jButton1 = new javax.swing.JButton();

jScrollPane1 = new javax.swing.JScrollPane();

jTextArea1 = new javax.swing.JTextArea();

setDefaultCloseOperation(javax.swing.WindowConstants.EXIT_ON_CLOSE);

jButton1.setText("Ejecutar hilos");

jButton1.addActionListener(new java.awt.event.ActionListener() {

public void actionPerformed(java.awt.event.ActionEvent evt) {

jButton1ActionPerformed(evt);

}

});

jTextArea1.setColumns(20);

jTextArea1.setRows(5);

jScrollPane1.setViewportView(jTextArea1);

javax.swing.GroupLayout layout = new javax.swing.GroupLayout(getContentPane());

getContentPane().setLayout(layout);

layout.setHorizontalGroup(

layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

.addGroup(layout.createSequentialGroup()

.addContainerGap()

.addGroup(layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

.addComponent(jButton1)

.addComponent(jScrollPane1, javax.swing.GroupLayout.PREFERRED_SIZE, 312, javax.swing.GroupLayout.PREFERRED_SIZE))

.addContainerGap(javax.swing.GroupLayout.DEFAULT_SIZE, Short.MAX_VALUE))

);

layout.setVerticalGroup(

layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)

.addGroup(layout.createSequentialGroup()

.addContainerGap()

.addComponent(jButton1)

.addGap(18, 18, 18)

.addComponent(jScrollPane1, javax.swing.GroupLayout.DEFAULT_SIZE, 422, Short.MAX_VALUE)

.addContainerGap())

);

pack();

}//

private void jButton1ActionPerformed(java.awt.event.ActionEvent evt) {

// TODO add your handling code here:

hilo1 = new Thread(this);

hilo2 = new Thread(this);

hilo3 = new Thread(this);

hilo1.start();

hilo2.start();

hilo3.start();

}

/**

* @param args the command line arguments

*/

public static void main(String args[]) {

/* Set the Nimbus look and feel */

//

/* If Nimbus (introduced in Java SE 6) is not available, stay with the default look and feel.

* For details see http://download.oracle.com/javase/tutorial/uiswing/lookandfeel/plaf.html

*/

try {

for (javax.swing.UIManager.LookAndFeelInfo info : javax.swing.UIManager.getInstalledLookAndFeels()) {

if ("Nimbus".equals(info.getName())) {

javax.swing.UIManager.setLookAndFeel(info.getClassName());

break;

}

}

} catch (ClassNotFoundException ex) {

java.util.logging.Logger.getLogger(ThreadsG.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);

} catch (InstantiationException ex) {

java.util.logging.Logger.getLogger(ThreadsG.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);

} catch (IllegalAccessException ex) {

java.util.logging.Logger.getLogger(ThreadsG.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);

} catch (javax.swing.UnsupportedLookAndFeelException ex) {

java.util.logging.Logger.getLogger(ThreadsG.class.getName()).log(java.util.logging.Level.SEVERE, null, ex);

}

//

/* Create and display the form */

java.awt.EventQueue.invokeLater(new Runnable() {

public void run() {

new ThreadsG().setVisible(true);

}

});

}

// Variables declaration - do not modify

private javax.swing.JButton jButton1;

private javax.swing.JScrollPane jScrollPane1;

private javax.swing.JTextArea jTextArea1;

// End of variables declaration

@Override

public void run() {

Thread ct = Thread.currentThread();

while (ct == hilo1) {

corredor1();

texto1=texto1 + "Corredor 1: " + c1 + "\n";

this.jTextArea1.setText(texto1); //se colcoca el resultado en el contro,jTextArea

System.out.println("Corredor 1: " + c1);

if (c1==500) break; //Al llegar a 500 ejecuciones detengo la ejecucin para observar el resultado

}

while (ct == hilo2) {

corredor2();

texto1=texto1 + "Corredor 2: " + c2 + "\n";

this.jTextArea1.setText(texto1); //se colcoca el resultado en el contro,jTextArea

System.out.println("Corredor 2: " + c2);

if (c2==500) break; //Al llegar a 500 ejecuciones detengo la ejecucin para observar el resultado

}

while (ct == hilo3) {

corredor3();

texto1=texto1 + "Corredor 3: " + c3 + "\n";

this.jTextArea1.setText(texto1); //se colcoca el resultado en el contro,jTextArea

System.out.println("Corredor 3: " + c3);

if (c3==500) break; //Al llegar a 500 ejecuciones detengo la ejecucin para observar el resultado

}

throw new UnsupportedOperationException("Not supported yet."); //To change body of generated methods, choose Tools | Templates.

}

}

Conclusiones: Con los hilos de ejecucin podemos terminar mucho ms rpido nuestra aplicacin, sobre todo cuando son grandes volmenes de datos o clculos que se tienen que procesar.