Pasar al contenido principal

Práctica 2

Versión para impresiónSend by email

En esta práctica se estudian las hebras en Java. Es el mismo ejemplo que la Práctica 1, pero realizado en Java.

 


Sonido.java - Ejemplo sencillo de creación de hebras en Java

import java.lang.Thread;
import java.util.Date;

/**
 * Ejemplo sencillo de hebras en Java
 */
public class Sonido {

    /**
     * Escribir la hora cada 1s
     */
    private static class escribirHora extends Thread {
        public void run() {
            while(true) {
                Date date = new Date();
                System.out.println(date.toString());
                try {
                    Thread.sleep(1000);                  // Importante, sleep puede lanzar excepcion
                } catch (InterruptedException e){};      // por lo que debe cazarse
            }
        }
    }
   
    /**
     * Emitir un sonido cada 5 s
     */
    private static class emitirSonido extends Thread {
        public void run() {
            while(true) {
                System.out.print("\007");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e){};
            }
        }
    }

    /**
     * Programa principal
     */
    public static void main(String[] args) {
        escribirHora hora = new escribirHora();
        emitirSonido sonido = new emitirSonido();
        hora.start();
        sonido.start();
        try {
            hora.join();
            sonido.join();
        } catch (InterruptedException e) {};
    }
}				        				        					 

Ejecución:

merlin@merlin-MacBookAir:~/Escritorio/LPRS/Practicas/2$ ls
Escribe.java  Hebras.java  Sonido.java
merlin@merlin-MacBookAir:~/Escritorio/LPRS/Practicas/2$ javac Sonido.java
merlin@merlin-MacBookAir:~/Escritorio/LPRS/Practicas/2$ ls
Escribe.java  Hebras.java  Sonido$1.class  Sonido.class  Sonido$emitirSonido.class  Sonido$escribirHora.class  Sonido.java
merlin@merlin-MacBookAir:~/Escritorio/LPRS/Practicas/2$ java Sonido
Tue Jun 12 13:34:59 CEST 2012
Tue Jun 12 13:35:01 CEST 2012
Tue Jun 12 13:35:02 CEST 2012
Tue Jun 12 13:35:03 CEST 2012
Tue Jun 12 13:35:04 CEST 2012
Tue Jun 12 13:35:05 CEST 2012
^Cmerlin@merlin-MacBookAir:~/Escritorio/LPRS/Practicas/2$

 

Hebras.java - Crea varias hebras implementadas en la clase Escribe.java

public class Hebras {

  static final int MAXHEBRAS=100;

  public static void main(String argv[]) {
    Escribe[] hebras= new Escribe[MAXHEBRAS];                  // Crea las hebras
    for (int i=0; i<argv.length; i++) {                        // Y para la longitud de los argumentos menos uno
      hebras[i]= new Escribe(i+1, argv[i]);                    // Crea la hebra
      hebras[i].start();                                       // y la inicia
    }
    for (int i=0; i<argv.length; i++) {                        // Espera a que terminen todas ellas
      try {
        hebras[i].join();
      }
      catch (Exception e) {
      }
      finally {
        System.out.println("Terminada la hebra "+i);           // imprimiendo cada mensaje de finalizacion
      }
    }
  }
}

 

Escribe.java - Extiende de la clase Thread. Imprime cada 'id' segundos una letra en el archivo pasado por parámetro.

import java.io.FileOutputStream;

public class Escribe extends Thread {

  protected int id;
  protected String argumento;

  public Escribe(int id, String arg) {		// Constructor, coge su id y el archivo al que guardar la salida
    this.id=id; argumento=arg;
  }

  public void run() {
    FileOutputStream salida;
    try {
      salida= new FileOutputStream(argumento);		// Se abre el archivo
      for (int i=0; i<20; i++) {
        Thread.sleep(1000*id);						// Y esperando "id" segundos
        salida.write('A'+id-1);						// Se imprime 'A' + id-1
      }
    } 
    catch (Exception e) {
      System.err.println("Error en la ejecucion de "+id+": "+e.getMessage());	// Si falla, se imprime el error
    }
  }
}

 

Ejecución:

merlin1@merlins1:~/Escritorio/Practicas/2$ ls
Escribe.java  Hebras.java  Sonido$1.class  Sonido.class  Sonido$emitirSonido.class  Sonido$escribirHora.class  Sonido.java
merlin1@merlins1:~/Escritorio/Practicas/2$ javac Hebras.java
merlin1@merlins1:~/Escritorio/Practicas/2$ ls
Escribe.class  Hebras.class  Sonido$1.class  Sonido$emitirSonido.class  Sonido.java
Escribe.java   Hebras.java   Sonido.class    Sonido$escribirHora.class
merlin1@merlins1:~/Escritorio/Practicas/2$ java Hebras
merlin1@merlins1:~/Escritorio/Practicas/2$ java Hebras test1.txt test2.txt
Terminada la hebra 0
Terminada la hebra 1
merlin1@merlins1:~/Escritorio/Practicas/2$ ls
Escribe.class  Hebras.class  Sonido$1.class  Sonido$emitirSonido.class  Sonido.java  test2.txt
Escribe.java   Hebras.java   Sonido.class    Sonido$escribirHora.class  test1.txt
merlin1@merlins1:~/Escritorio/Practicas/2$ cat test1.txt
AAAAAAAAAAAAAAAAAAAAmerlin1@merlins1:~/Escritorio/Practicas/2$ cat test2.txt
BBBBBBBBBBBBBBBBBBBBmerlin1@merlins1:~/Escritorio/Practicas/2$

 

Resultados Pedidos:

1- Explicación del funcionamiento de los dos programas, comparando con el capítulo 1.

El primero de ellos, Sonido.java, hace la misma función que el primero de C. Crea dos hebras, una imprime la hora cada segundo mientras la otra genera un sonido (imprimiendo '\a') cada 5 segundos.

El segundo, igual que en el ejemplo de C, crea tantas hebras como parámetros se pasen (menos uno, por el parámetro de la llamada al propio programa) y guarda en un archivo con el nombre de cada parámetro una letra asociada con el identificador de la hebra hasta 20 veces esperando 'id' segundos. Espera a la terminación de cada hebra para informar de su fin.

2- Realizar el mismo programa, pero implementando la interfaz Runnable.

Hebras.java - Crea varias hebras implementadas en la clase Escribe.java

public class Hebras {

  static final int MAXHEBRAS=100;

  public static void main(String argv[]) {
    Escribe[] escritores= new Escribe[MAXHEBRAS];				// Crea el array de escritores
    Thread[] hebras = new Thread[MAXHEBRAS];				        // y el array de hebras
    for (int i=0; i<argv.length; i++) {						// Y para la longitud de los argumentos menos uno
      escritores[i]= new Escribe(i+1, argv[i]);				        // Crea el objeto escritor con su id
      hebras[i] = new Thread(escritores[i]);				        // Crea la hebra asociada al escritor
      hebras[i].start();							// y la inicia
    }
    for (int i=0; i<argv.length; i++) {						// Espera a que terminen todas ellas
      try {
        hebras[i].join();
      } 
      catch (Exception e) {
      } 
      finally {
        System.out.println("Terminada la hebra "+i);		// imprimiendo cada mensaje de finalizacion
      }
    }
  }
}

 

Escribe.java - Extiende de la clase Thread. Imprime cada 'id' segundos una letra en el archivo pasado por parámetro.

import java.io.FileOutputStream;

public class Escribe implements Runnable {

	protected int id;
	protected String argumento;
	
	public Escribe(int id, String arg) {
		this.id=id; argumento=arg;
	}
	
	public void run() {
		FileOutputStream salida;
		try {
			salida= new FileOutputStream(argumento);		// Se abre el archivo
			for (int i=0; i<20; i++) {
				Thread.sleep(1000*id);				// Y esperando "id" segundos
				salida.write('A'+id-1);				// Se imprime 'A' + id-1
			}
		}
		catch (Exception e) {
			System.err.println("Error en la ejecucion de "+id+": "+e.getMessage());	// Si falla, se imprime el error
		}
	}
}

 

La diferencia principal es que al implementar la clase runnable puedes heredar de otra clase, mientras que si lo haces heredando de Thread no puede heredar de otra más (no existe herencia múltiple en Java a diferencia de C++, Perl o Python).

El único cambio en código es que primeramente se crea el objeto Escribe y después se crea la hebra asociada al objeto (que ejecutará el método run()).

 

Ejecución:

merlin1@merlins1:~/Escritorio/Practicas/2/Runnable$ ls
Escribe.java  Hebras.java
merlin1@merlins1:~/Escritorio/Practicas/2/Runnable$ javac Hebras.java
merlin1@merlins1:~/Escritorio/Practicas/2/Runnable$ ls
Escribe.class  Escribe.java  Hebras.class  Hebras.java
merlin1@merlins1:~/Escritorio/Practicas/2/Runnable$ java Hebras test1.txt test2.txt
Terminada la hebra 0
Terminada la hebra 1
merlin1@merlins1:~/Escritorio/Practicas/2/Runnable$ ls
Escribe.class  Escribe.java  Hebras.class  Hebras.java  test1.txt  test2.txt
merlin1@merlins1:~/Escritorio/Practicas/2/Runnable$ cat test1.txt
AAAAAAAAAAAAAAAAAAAAmerlin1@merlins1:~/Escritorio/Practicas/2/Runnable$ cat test2.txt
BBBBBBBBBBBBBBBBBBBBmerlin1@merlins1:~/Escritorio/Practicas/2/Runnable$

 

AdjuntoTamaño
Hebras.java879 bytes
Escribe.java624 bytes