Multithread

Multithread (multihilo) en Java

MULTITHREAD

Multithread en Java es una característica que permite realizar más de una tarea a la vez (multitarea) obteniendo una ejecución más rápida de la aplicación y alcanzando un mayor rendimiento del procesador. El multithread o multihilo se basa en threads o hilos y estos threads son los encargados de realizar las distintas tareas del programa. Los threads pueden ser iniciados, detenidos o parados y trabajar en segundo plano permitiendo obtener una mejor experiencia al usuario, ya sea por menores tiempos de espera durante la ejecución o de obtención de resultados. 

Debido a las contínuas mejoras de los procesadores que, a velocidad imperial aumentan de núcleos, toma importancia el multithread. Cada Thread representa un núcleo, es decir, si el programa tiene varios hilos, el sistema exige al procesador trabajar con los núcleos que dispone para ejecutar esos hilos o tareas. Aun cuando existe solamente un núcleo los hilos pueden obtener cierto tiempo de actividad al usuario, por tanto,  es recomendable trabajar con threads siempre que se pueda. Este concepto multihilo es muy similar al multiproceso que utilizan los sistemas operativos, que permiten descomprimir un archivo, reproducir varias cámaras de vigilancia y ver una película online a la vez. Y mucho más... solo hay que acceder al administrador de tareas de Windows o teclear en una terminal de Linux el comando ps -A para observar la cantidad de procesos que se encuentran trabajando, pero que no se visualizan por pantalla.

Trabajar con hilos, se hace posible mediante dos fórmulas. Una, basada en implementar la interface Runnable, y otra basada en extender de la clase Thread que implementa la interface Runnable En el primer caso tan solo requiere el método run y en el segundo caso se dispone de todos los métodos de la clase Thread. Tanto en un caso como en otro es imprescindible sobreescribir el método run(),. A continuación una lista con los métodos más utilizados de la clase Thread que permiten trabajar el estado de los hilos.

run()

Este método es indispensable, tanto si se implementa la interface Runnable como si se hereda de Thread (Thread la implementa) y es donde se incluye la funcionalidad del hilo. 

start()

Inicia la ejecución de un hilo realizando la ejecución del método run().

sleep()

Cambia el estado del hilo a la fase de dormido durante un tiempo determinado. El tiempo se determina pasándole un parámetro en milisegundos.

stop()

Detiene la ejecución del hilo y lo destruye.

suspend()

Detiene la ejecución del hilo pero no lo destruye.

resume()

Retoma la ejecución del hilo suspendida anteriormente con suspend().

getName()

Obtiene el nombre establecido anteriormente por setName(). Si no se ha establecido se obtiene un nombre definido por defecto(Thread-0, Thread-1,...)

setName()

Establece el nombre pasado por parámetro al hilo.

getPriority()

Obtiene el nivel de prioridad de ejecución. El nivel se compone de un rango del 1 al 10. El nivel 1 indica prioridad máxima (MAX_PRIORITY), el nivel 5 indica prioridad normal (NORM_PRIORITY) siendo el nivel que inicia el hilo por defecto y el nivel 10 indica prioridad mínima(MIN_PRIORITY).

setPriority()

Establece el nivel de prioridad del hilo.

yield()

Cede el paso a otro hilo y se mantiene en espera temporalmente. Durante el tiempo de espera se mantiene en una fase intermedia preparada para volver a retomar el hilo.

currentThread()

Devuelve el objeto Thread que inicia el método.

DIFERENCIA ENTRE UN PROYECTO CON UN ÚNICO HILO Y UN PROYECTO MULTIHILO

El código que sigue a continuación se divide en dos proyectos que permiten diferenciar claramente de trabajar sin hilos o un único hilo a trabajar con varios hilos. Los dos se basan en un taller de reparación de automóviles y están compuestos solamente por dos clases, una que es casi idéntica en los dos proyectos y la otra que es donde se encuentran las diferencias de trabajar con hilos a trabajar sin ellos. 

PROYECTO ÚNICO HILO

Este proyecto está compuesto por la clase Coche y la clase Reparación que también contiene el método principal(main). La clase Coche es una clase muy básica, formada por un constructor que asigna la marca y modelo del coche y contiene cuatro métodos, por un lado el getter y el setter del coche que trabajan con datos de tipo cadena, marca y modelo respectivamente, y por otro lado el getter y el setter de las averías que hay que reparar en cada coche, que trabajan con datos de tipo entero en forma de array y que representan una lista de tiempos fijados para cada reparación. Para entender el orden del array de averías se puede suponer que un coche que entra en el taller, puede precisar de tres reparaciones, la primera tiene un tiempo fijado de 15 minutos, la segunda de 35 y la tercera de 10, por tanto el array de averías sería el siguiente: {15,35,10}. 

Clase Coche

  1. package unicohilo;
  2. public class Coche {
  3. private String marca;
  4. private String modelo;
  5. private int[] averias;
  6. public Coche(String marca, String mod){
  7. this.marca=marca;
  8. this.modelo=mod;
  9. }
  10. public String getCoche(){
  11. return this.marca+" "+this.modelo;
  12. }
  13. public void setCoche(String marca,String mod){
  14. this.marca=marca;
  15. this.modelo=mod;
  16. }
  17. public int[] getAverias(){
  18. return this.averias;
  19. }
  20. public void setAverias(int[] averias){
  21. this.averias=averias;
  22. }
  23. }

La clase Reparacion está compuesta por un constructor, dos métodos que manejan el único hilo y el método principal.

El constructor asigna un dato de tipo Coche basado en la clase Coche, un array de tipo entero que contiene los tiempos de reparación de cada avería y un dato de tipo long que almacena el tiempo en milisegundos del comienzo de las reparaciones. Este último solo sirve para mostrar la diferencia de tiempo empleado en un proyecto y en otro, por tanto, es un parámetro independiente sin ninguna relación con los hilos.

El método repararCoche es el encargado de manejar el hilo, está compuesto, por un lado, por varios mensajes que permiten distinguir a que coche pertenece cada cambio del hilo, y por otro, por un bucle for  que realiza una iteración asociada con el array de las averías.  Por cada avería de cada coche, realiza una iteración y en cada iteración realiza una llamada al método repararAveria() que es el cambia de estado el hilo a fase de dormido. Esta fase es iniciada mediante el método sleep(), perteneciente a la clase Thread y lo que hace es pausar el flujo del hilo durante el tiempo fijado de cada avería expresado en cada elemento del array.

Por último el método principal que comienza creando los coches, asigna la cantidad y los tiempos de las averías (tiempos pequeños y en segundos para el ejemplo), continua creando las reparaciones de cada coche y finalmente realiza la llamada al método repararCoche() que se encarga de la reparación total de cada coche.

Clase Reparacion

  1. package unicohilo;
  2. public class Reparacion {
  3. private Coche coche;
  4. private int[] tiempoReparacion;
  5. private long inicioReparaciones;
  6. public Reparacion(Coche coche,int[]tiempo,long t){
  7. this.coche=coche;
  8. this.tiempoReparacion=tiempo;
  9. this.inicioReparaciones = t;
  10. }
  11. public void repararCoche(){
  12. System.out.println("El coche "+this.coche.getCoche()+" ha entrado en taller");
  13. for(int i=0;i<this.tiempoReparacion.length;i++){
  14. repararAveria(this.tiempoReparacion[i]);
  15. System.out.println("El coche "+this.coche.getCoche()+" tiene "+(i+1)+" averías reparadas de "+this.tiempoReparacion.length);
  16. }
  17. System.out.println("El coche "+this.coche.getCoche()+" ha sido reparado y está listo para su entrega");
  18. System.out.println("El tiempo transcurrido desde el inicio de las reparaciones ha sido de "+(System.currentTimeMillis()-this.inicioReparaciones)/1000+" segundos");
  19. }
  20. public void repararAveria(int t){
  21. try {
  22. Thread.sleep(t*1000);
  23. } catch (InterruptedException ex) {
  24. Thread.currentThread().interrupt();
  25. }
  26. }
  27. public static void main(String[] args) {
  28. Coche coche1 = new Coche("Ford","Focus");
  29. coche1.setAverias(new int[]{2,3,4});
  30. Coche coche2 = new Coche("Seat", "Ibiza");
  31. coche2.setAverias(new int[] {1,8,10});
  32. Coche coche3 = new Coche("VolskWagen","Passat");
  33. coche3.setAverias(new int[]{5,7});
  34. long horaEntrada=System.currentTimeMillis();
  35. Reparacion reparacion1=new Reparacion(coche1,coche1.getAverias(),horaEntrada);
  36. Reparacion reparacion2 = new Reparacion(coche2,coche2.getAverias(),horaEntrada);
  37. Reparacion reparacion3 = new Reparacion(coche3,coche3.getAverias(),horaEntrada);
  38. reparacion1.repararCoche();
  39. reparacion2.repararCoche();
  40. reparacion3.repararCoche();
  41. }
  42. }

Resultado único hilo


PROYECTO MULTIHILO

El proyecto con multihilo está formado por la clase CocheMultithread y la clase ReparacionMultithread que contiene la clase principal(main). La clase CocheMultithread es idéntica a la clase Coche, la única diferencia se encuentra en el nombre de la clase.

Clase CocheMultithread

  1. package multihilo;
  2. public class CocheMultithread {
  3. private String marca;
  4. private String modelo;
  5. private int[] averias;
  6. public CocheMultithread(String marca, String mod){
  7. this.marca=marca;
  8. this.modelo=mod;
  9. }
  10. public String getCoche(){
  11. return this.marca+" "+this.modelo;
  12. }
  13. public void setCoche(String marca,String mod){
  14. this.marca=marca;
  15. this.modelo=mod;
  16. }
  17. public int[] getAverias(){
  18. return this.averias;
  19. }
  20. public void setAverias(int[] averias){
  21. this.averias=averias;
  22. }
  23. }

La clase ReparacionMultithread es similar a la clase Reparacion con mínimas diferencias. Una de ellas es que hereda de la clase Thread, la otra es que el método repararCoche() se ha convertido en el método run() y la última es que el método main ya no realiza la llamada al método repararCoche() si no que realiza la llamada al método start()

Clase ReparacionMultithread

  1. package multihilo;
  2. public class ReparacionMultithread extends Thread {
  3. private CocheMultithread coche;
  4. private int[] tiempoReparacion;
  5. private long inicioReparaciones;
  6. public ReparacionMultithread(CocheMultithread coche,int[]tiempo,long t){
  7. this.coche=coche;
  8. this.tiempoReparacion=tiempo;
  9. this.inicioReparaciones = t;
  10. }
  11. public void run(){
  12. System.out.println("El coche "+this.coche.getCoche()+" ha entrado en taller");
  13. for(int i=0;i<this.tiempoReparacion.length;i++){
  14. repararAveria(this.tiempoReparacion[i]);
  15. System.out.println("El coche "+this.coche.getCoche()+" tiene "+(i+1)+" averías reparadas de "+this.tiempoReparacion.length);
  16. }
  17. System.out.println("El coche "+this.coche.getCoche()+" ha sido reparado y está listo para su entrega");
  18. System.out.println("El tiempo transcurrido desde el inicio de las reparaciones ha sido de "+(System.currentTimeMillis()-this.inicioReparaciones)/1000+" segundos");
  19. }
  20. public void repararAveria(int t){
  21. try {
  22. Thread.sleep(t*1000);
  23. } catch (InterruptedException ex) {
  24. Thread.currentThread().interrupt();
  25. }
  26. }
  27. public static void main(String[] args) {
  28. CocheMultithread coche1 = new CocheMultithread("Ford","Focus");
  29. coche1.setAverias(new int[]{2,3,4});
  30. CocheMultithread coche2 = new CocheMultithread("Seat", "Ibiza");
  31. coche2.setAverias(new int[]{1,8,10});
  32. CocheMultithread coche3 = new CocheMultithread("VolskWagen","Passat");
  33. coche3.setAverias(new int[]{5,7});
  34. long horaEntrada=System.currentTimeMillis();
  35. ReparacionMultithread reparacion1=new ReparacionMultithread(coche1,coche1.getAverias(),horaEntrada);
  36. ReparacionMultithread reparacion2 = new ReparacionMultithread(coche2,coche2.getAverias(),horaEntrada);
  37. ReparacionMultithread reparacion3 = new ReparacionMultithread(coche3,coche3.getAverias(),horaEntrada);
  38. reparacion1.start();
  39. reparacion2.start();
  40. reparacion3.start();
  41. }
  42. }

Resultado multihilo



Comentarios: 0

Para poder comentar es necesario iniciar sesión



Este dominio utiliza cookies de terceros para crear estadísticas y publicidad personalizada. Si continúa navegando está aceptando su uso