Anteriormente hemos visto:
Ahora veremos:
En el tutorial anterior os mostré un ejemplo de 4 hilos que imprimían un saludo, en este tutorial vamos a ver cómo sacar beneficio de la creación de hilos, para ello tomemos este ejemplo:
public class secuencial {
public static int sumatorio(int n) {
int resultado = 0;for (int i = 0; i < n; ++i) {
resultado += i;
}
return resultado;
}
public static void main(String[] args) {
/*
* Este es un ejemplo de ejecución secuencial. Tendremos solo UN proceso para la
* toda la ejecución del programa.
*/
long vector[] = new long[N];int N = 200000;
vector = new long[N];// Calculo del sumatorio de cada indice y guardado en el vector.
long start = System.currentTimeMillis();for (int i = 0; i < vector.length; ++i) {
vector[i] = sumatorio(i);
}
long end = System.currentTimeMillis();System.out.println("Elapsed time = " + (end - start));
}
}
En este caso la ejecución de este programa será realizada solo por un hilo(el principal), este hilo tendra que realizar N iteraciones del bucle for(además de las llamadas a la función sumatorio que esto supone), ahora si creamos más hilos podremos dividir la carga de trabajo, ya que podríamos indicarles que cada hilo se encargue de asignar valores a una parte(distinta) del vector, de esto se trata el particionamiento del trabajo. En el siguiente código os voy a mostrar un ejemplo un código(Principal) que utiliza una clase(Hilo) que herenda de Thread:
public class Principal {
// Esta clase se encargara de utilizar la clase Hilo que hemos definido
public static void main(String[] args) throws InterruptedException {
int numeroHilos = 4;
Hilo[] hilos = new Hilo[numeroHilos];int tam = 20000;
long[] vector = new long[tam];// Para obtener un intervalo distinto en cada hilo se utilizaran las siguiente// variables auxiliares, fijate que el primer intervalo esta definido asi [0,// elementosPorHilo).int elementosPorHilo = tam / numeroHilos;int inicio = 0, fin = elementosPorHilo;for (int i = 0; i < numeroHilos; i++) {
hilos[i] = new Hilo(inicio, fin, vector);
inicio = fin; // El inicio del siguiente hilo sera el fin del anterior, asi conseguimos que// cada uno procese una zona distinta.
fin = fin + elementosPorHilo; // Actualizar el fin acorde al inicio.
}
// Ahora lanzamos la ejecución de los hilos, en el caso de heredar de Thread se// llama a start() directamente.
long start = System.currentTimeMillis();for (int i = 0; i < numeroHilos; i++) {
hilos[i].start();
}
// Ahora hay que ESPERAR a que terminen su procesamiento, para eso usamos el// método join() heredado de la clase thread.for (int i = 0; i < numeroHilos; i++) {
hilos[i].join();
}
long end = System.currentTimeMillis();System.out.println("Elapsed time for a size = " + tam + " with 4 threads = " + (end - start));
}
}
publicclassHiloextendsThread{
privateint inicio, fin;
privatelong[] referencia;
publicHilo(int inicio, int fin, long[] referencia){
// En el ctor. indicamos el intervalo[inicio, fin) que procesara cada hilothis.inicio = inicio;
this.fin = fin;
this.referencia = referencia;
}
publicvoidrun(){
// Este método es el que se ejecutará tras haber usado start()for (int i = this.inicio; i < this.fin; i++) {
// Con este bucle denotamos las iteraciones que debe realizar cada hilo.
referencia[i] = sumatorio(i);
}
}
publicintsumatorio(int n){
int resultado = 0;
for (int i = 0; i < n; ++i) {
resultado += i;
}
return resultado;
}
}
Ahora te voy a mostrar una gráfica comparativa de tiempos de ejecución:
A mayor tamaño, mayor es el beneficio del empleo de hilos.