Buenas,
Cada vez que creas un thread, esto tiene un importante coste a nivel de recursos, ya que cada thread tiene su propio heap y stack de ejecucion. Por eso se te queda sin memoria.
Por otro lado lo que intentas es muy ineficiente, ya que el numero de cores de tu maquina es limitado. Ten en cuenta que cuando ejecutas muchos threads sobre un mismo core, este tiene que estar cambiando de contexto constantemente (
http://es.wikipedia.org/wiki/Cambio_de_contexto)
El uso de muchos threads esta bien cuando se quieren ejecutar muchas tareas concurrentes sin dejar bloqueado al usuario. Por ejemplo un servidor, si no utilizase hilos, solo podria procesar una peticion al mismo tiempo.
Sin embargo tu caso es distinto, ya que no quieres ejecutar muchas tareas sino dividir una sola muy pesada. Esta es la diferencia entre concurrencia y paralelismo.
Lo que deberias hacer para conseguir el mayor rendimiento posible es basarte en el numero de cores de tu maquina:
Ese es el numero de thread optimo para tu calculo.
Por otro lado, debes dividir bien las tareas. No puedes asignar a cada thread de forma secuencial.
Por ejemplo si tienes 4 cores y haces esto:
Thread 1: de 1 a 250000
Thread 2: de 250001 a 500000
[...]
Es muy mala idea ya que el algoritmo de calculo de primos es de complejidad lineal (O(n)) y por tanto, a mayor valor de n mas va a tardar. Lo mejor es que vayas asignando a cada core pequenos packs a procesar y segun vayan terminando le asignas nuevos hasta terminar.
En cualquier caso, si usas Java 8, esta chupado:
Código Java:
Ver original/**
*
* @author Profesor_Falken
*/
public class ParallelIsPrime {
private boolean isPrime(long n) {
return n > 1 && rangeClosed(2, (long) sqrt(n)).noneMatch(divisor -> n % divisor == 0);
}
private void printPrimes() {
long[] primos = range(1, 1_000_000).parallel().filter(this::isPrime).toArray();
for (int i = 0; i<primos.length; i++) {
System.
out.
println(primos
[i
]); }
}
public static void main
(String[] args
) { new ParallelIsPrime().printPrimes();
}
}
Un saludo