Mostrando entradas con la etiqueta pre. Mostrar todas las entradas
Mostrando entradas con la etiqueta pre. Mostrar todas las entradas

viernes, 2 de marzo de 2012

Pool de hilos

Hoy voy hablar sobre la clase "ExecutorService", con esta clase no permite gestionar un pool de hilos. A continuación pongo un ejemplo de uso de la clase con comentarios de cada uno de los ejemplos.

import java.util.Collection;
import java.util.HashSet;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class Main {
 private ExecutorService executor;
 
 
 /**
 *Clase para terminar todos los hilos
 */
 private void endExecutor(){
  executor.shutdown();
  try 
  {
   if (!executor.awaitTermination(60, TimeUnit.SECONDS)) 
   {
    executor.shutdownNow();
    if (!executor.awaitTermination(60, TimeUnit.SECONDS))
    {
     System.err.println("executor  no ha terminado");
    }
   }
  } catch (InterruptedException ie) {
   executor.shutdownNow();
   Thread.currentThread().interrupt();
  }
 }
 /**
  * Crea un pool que va a ir creando threads conforme se vayan necesitando
  * si hay threads libres, se ponen las tareas a procesarse dentro de dichos threads, y
  * las tareas faltantes se procesan en threads nuevos
  */
 public void newCachedThreadRool(){
  this.executor = Executors.newCachedThreadPool();
  for(int i=0; i < 5; i++){
   this.executor.execute(new Handler("Hilo_"+i));
  }
  endExecutor();
 }
 
 /**
  * crea un pool con el número de threads indicado; dichos threads siempre estarán listos 
  * para procesar tareas. El pool maneja también una cola de tareas; cada thread toma una
  * tarea de la cola y la procesa, y al terminar toma otra tarea de la cola para procesarla, etc en un ciclo
  */
 public void newFixedThreadPool(){
  this.executor = Executors.newFixedThreadPool(3);
  for(int i=0; i < 5; i++){
   this.executor.execute(new Handler("Hilo_"+i));
  }
  endExecutor();
 }
 
 /**
  * crea un pool de un solo thread, con una cola en donde se ponen las tareas a procesar; 
  * el thread toma una tarea de la cola, la procesa y toma la siguiente, en un ciclo. 
  */
 public void newSingleThreadExecutor(){
  this.executor = Executors.newSingleThreadExecutor();
  for(int i=0; i < 5; i++){
   this.executor.execute(new Handler("Hilo_"+i));
  }
  endExecutor();
 }
 
 /**
  * crea un pool que va a ejecutar tareas programadas cada cierto tiempo, ya sea una sola 
  * vez o de manera repetitiva. Es parecido a un timer, pero con la diferencia de que puede 
  * tener varios threads que irán realizando las tareas programadas conforme se desocupen. 
  * También hay una versión de un solo thread.
  */
 public void newScheduledThreadPool(){
  this.executor = Executors.newScheduledThreadPool(3);
  for(int i=0; i < 5; i++){
   this.executor.execute(new Handler("Hilo_"+i));
  }
  endExecutor();
 }

/**
  * Si queremos que despues de la excución nos devuelva algo tenemos que implemetar la 
  * interfaz Callabe
  */
 public void callableThread() throws ExecutionException, InterruptedException{
  this.executor = Executors.newCachedThreadPool();
  Collection callableResults = new HashSet();
  for(int i=0; i < 3; i++){
   callableResults.add(new CallableResult("Callable_"+i));
  }
  //solo uno
  Future future = executor.submit((CallableResult)callableResults.toArray()[0]);
  //devuelve el resultado de una tare completa correcamente
  String result = executor.invokeAny(callableResults);
  //Espera a que se termine todos los hilos
  List<"Future"> futures = executor.invokeAll(callableResults);
  
  System.out.println("future.get() = " + future.get());
  System.out.println("Result invoke any = " + result);
  for(int i=0; i < futures.size(); i++){
   System.out.println("Result invoke all = " + futures.get(i).get());
  }
 }

 public static void main(String[] args) {
  try
  {
   System.out.println("El numero de procesadores : "+Runtime.getRuntime().availableProcessors());
   new Main().callableThread();
  }catch (Exception e) {
   System.out.println(e.getMessage());
  }
 }

}
Cuando copies el código teneies que citar la comillas doble Future porque no me daba un error el editor de html. A continuación la clase Handler
import java.util.Random;

public class Handler implements Runnable {
 private String nombreHilo; 
 private Random generador;
 private int dormir;

 public Handler(String name) {
  this.nombreHilo = name;
  this.generador = new Random();
  this.dormir = generador.nextInt(5000);
 }

 public void run() {
  try 
  {
   System.out.println("\t Voy a dormir "+this.dormir+" : "+nombreHilo);
   Thread.sleep(this.dormir);
  }
  catch (InterruptedException exception) {
   exception.printStackTrace();
  }
  System.out.println("\t Ya he terminado de dormir : "+nombreHilo);
 } 
}


 public static void main(String[] args) {
  try
  {
   System.out.println("El numero de procesadores : "+Runtime.getRuntime().availableProcessors());
   new Main().callableThread();
  }catch (Exception e) {
   System.out.println(e.getMessage());
  }
 }

}
Y por ultimo la clase CallableResult
import java.util.Random;
import java.util.concurrent.Callable;

public class CallableResult implements Callable{
 private String nombreHilo; 
 private Random generador;
 private int dormir;

 public CallableResult(String name) {
  this.nombreHilo = name;
  this.generador = new Random();
  this.dormir = generador.nextInt(5000);
 }
 
 public String call() throws Exception {
  try 
  {
   System.out.println("\t Voy a dormir "+this.dormir+" : "+nombreHilo);
   Thread.sleep(this.dormir);
   System.out.println("\t Ya he terminado de dormir : "+nombreHilo);
   return "terminado "+nombreHilo;
  }
  catch (InterruptedException exception) {
   return exception.getMessage();
  }
 }
}

Con esto es todo sobre la clase ExecutorService