¿Cuántos hilos puede admitir una máquina virtual Java? ¿Esto varía según el proveedor? por sistema operativo? ¿otros factores?
¿Cuántos hilos puede admitir una máquina virtual Java? ¿Esto varía según el proveedor? por sistema operativo? ¿otros factores?
Respuestas:
Esto depende de la CPU que esté utilizando, del sistema operativo, de lo que estén haciendo otros procesos, de la versión de Java que esté utilizando y de otros factores. He visto que un servidor de Windows tiene más de 6500 subprocesos antes de apagar la máquina. La mayoría de los hilos no estaban haciendo nada, por supuesto. Una vez que la máquina alcanzó alrededor de 6500 subprocesos (en Java), toda la máquina comenzó a tener problemas y se volvió inestable.
Mi experiencia muestra que Java (versiones recientes) puede consumir felizmente tantos subprocesos como la computadora puede alojar sin problemas.
Por supuesto, debe tener suficiente RAM y debe haber iniciado Java con suficiente memoria para hacer todo lo que los subprocesos están haciendo y tener una pila para cada subproceso. Cualquier máquina con una CPU moderna (las dos generaciones más recientes de AMD o Intel) y con 1 a 2 gigabytes de memoria (dependiendo del sistema operativo) puede admitir fácilmente una JVM con miles de subprocesos.
Si necesita una respuesta más específica que esta, su mejor opción es hacer un perfil.
Um, mucho.
Hay varios parámetros aquí. La VM específica, además de que generalmente también hay parámetros de tiempo de ejecución en la VM. Eso es algo impulsado por el sistema operativo: ¿qué soporte tiene el sistema operativo subyacente para los subprocesos y qué limitaciones les impone? Si la máquina virtual realmente utiliza hilos de nivel de sistema operativo, el viejo y bueno hilo rojo / hilo verde.
Lo que significa "apoyo" es otra pregunta. Si escribes un programa Java que es algo así como
class DieLikeADog {
public static void main(String[] argv){
for(;;){
new Thread(new SomeRunaable).start();
}
}
}
(y no me quejo de los pequeños detalles de sintaxis, estoy tomando mi primera taza de café), entonces seguramente debería esperar que se ejecuten cientos o miles de hilos. Pero crear un subproceso es relativamente costoso, y la sobrecarga del planificador puede ser intensa; no está claro que pueda hacer que esos hilos hagan algo útil.
Bien, no pude resistirme. Aquí está mi pequeño programa de prueba, con un par de adornos:
public class DieLikeADog {
private static Object s = new Object();
private static int count = 0;
public static void main(String[] argv){
for(;;){
new Thread(new Runnable(){
public void run(){
synchronized(s){
count += 1;
System.err.println("New thread #"+count);
}
for(;;){
try {
Thread.sleep(1000);
} catch (Exception e){
System.err.println(e);
}
}
}
}).start();
}
}
}
En OS / X 10.5.6 en Intel y Java 6 5 (ver comentarios), esto es lo que obtuve
Nuevo hilo # 2547 Nuevo hilo # 2548 Nuevo hilo # 2549 No se puede crear hilo: 5 Nuevo hilo # 2550 Excepción en el hilo "principal" java.lang.OutOfMemoryError: no se puede crear un nuevo hilo nativo en java.lang.Thread.start0 (Método nativo) en java.lang.Thread.start (Thread.java:592) en DieLikeADog.main (DieLikeADog.java:6)
Después de leer la publicación de Charlie Martin, tenía curiosidad por saber si el tamaño del montón hace alguna diferencia en la cantidad de hilos que puede crear, y el resultado me dejó totalmente estupefacto.
Usando JDK 1.6.0_11 en Vista Home Premium SP1, ejecuté la aplicación de prueba de Charlie con diferentes tamaños de almacenamiento dinámico, entre 2 MB y 1024 MB.
Por ejemplo, para crear un montón de 2 MB, invocaría la JVM con los argumentos -Xms2m -Xmx2m.
Aquí están mis resultados:
2 mb --> 5744 threads
4 mb --> 5743 threads
8 mb --> 5735 threads
12 mb --> 5724 threads
16 mb --> 5712 threads
24 mb --> 5687 threads
32 mb --> 5662 threads
48 mb --> 5610 threads
64 mb --> 5561 threads
96 mb --> 5457 threads
128 mb --> 5357 threads
192 mb --> 5190 threads
256 mb --> 5014 threads
384 mb --> 4606 threads
512 mb --> 4202 threads
768 mb --> 3388 threads
1024 mb --> 2583 threads
Entonces, sí, el tamaño del montón definitivamente importa. Pero la relación entre el tamaño de almacenamiento dinámico y el recuento máximo de subprocesos es INVERSAMENTE proporcional.
Lo cual es raro.
Sé que esta pregunta es bastante antigua, pero solo quiero compartir mis hallazgos.
Mi computadora portátil es capaz de manejar un programa que genera 25,000
hilos y todos esos hilos escriben algunos datos en la base de datos MySql a intervalos regulares de 2 segundos.
Ejecuté este programa con 10,000 threads
para 30 minutes continuously
entonces también mi sistema era estable y pude hacer otras operaciones normales como navegar, abrir, cerrar otros programas, etc.
Con 25,000 threads
sistema slows down
pero sigue siendo sensible.
Con el 50,000 threads
sistema al stopped responding
instante y tuve que reiniciar mi sistema manualmente.
Los detalles de mi sistema son los siguientes:
Processor : Intel core 2 duo 2.13 GHz
RAM : 4GB
OS : Windows 7 Home Premium
JDK Version : 1.6
Antes de ejecutar configuré el argumento jvm -Xmx2048m
.
Espero eso ayude.
El máximo teórico absoluto es generalmente el espacio de dirección de usuario de un proceso dividido por el tamaño de la pila de hilos (aunque en realidad, si toda su memoria está reservada para las pilas de hilos, no tendrá un programa que funcione ...).
Entonces, en Windows de 32 bits, por ejemplo, donde cada proceso tiene un espacio de dirección de usuario de 2 GB, lo que le da a cada subproceso un tamaño de pila de 128K, esperaría un máximo absoluto de 16384 subprocesos (= 2 * 1024 * 1024/128). En la práctica, encuentro que puedo iniciar unos 13,000 bajo XP.
Entonces, creo que eres en esencia en si (a) se puede administrar malabarismo que muchos hilos en el código y no hacen cosas tontas, obviamente, (como haciendo que todos se espera en el mismo objeto a continuación, llamar notifyAll () ...), y (b) si el sistema operativo puede. En principio, la respuesta a (b) es "sí" si la respuesta a (a) también es "sí".
Por cierto, puede especificar el tamaño de la pila en el constructor del subproceso ; no necesita (y probablemente no debería) meterse con los parámetros de VM para esto.
Recuerdo haber escuchado una charla de Clojure donde pudo ejecutar una de sus aplicaciones en una máquina especializada en una feria con miles de núcleos (¿9000?), Y los cargó a todos. Desafortunadamente, no puedo encontrar el enlace en este momento (¿ayuda?).
Basado en eso, creo que es seguro decir que el hardware y su código son los factores limitantes, no la JVM.
Después de jugar con la clase DieLikeACode de Charlie, parece que el tamaño de la pila de subprocesos de Java es una gran parte de la cantidad de subprocesos que puede crear.
-Xss establece el tamaño de la pila de hilos java
Por ejemplo
java -Xss100k DieLikeADog
Pero, Java tiene la interfaz Ejecutor . Lo usaría, podrá enviar miles de tareas Runnable y hacer que el Ejecutor procese esas tareas con un número fijo de subprocesos.
Runnable
/ Callable
realmente necesita ejecutarse continuamente, como cuando tiene que manejar la comunicación. Pero es perfecto para consultas SQL.
Al menos en Mac OS X 10.6 32 bits, el sistema operativo tiene un límite (2560). Verifique este hilo de stackoverflow .
El número máximo de hilos depende de lo siguiente:
Información adicional para sistemas linux modernos (systemd).
Hay muchos recursos sobre esto de valores que pueden necesitar ajustes (como Cómo aumentar el número máximo de subprocesos JVM (Linux 64bit) ); sin embargo, se impone un nuevo límite mediante el límite systemd "TasksMax" que establece pids.max en el cgroup.
Para las sesiones de inicio de sesión, el valor predeterminado de UserTasksMax es el 33% del límite del núcleo pids_max (generalmente 12,288) y se puede anular en /etc/systemd/logind.conf.
Para los servicios, el valor predeterminado de DefaultTasksMax es el 15% del límite del núcleo pids_max (generalmente 4,915). Puede anularlo para el servicio configurando TasksMax en "systemctl edit" o actualizando DefaultTasksMax en /etc/systemd/system.conf
Puede procesar cualquier cantidad de hilos; No hay límite. Ejecuté el siguiente código mientras veía una película y usaba NetBeans, y funcionó correctamente / sin detener la máquina. Creo que puedes mantener aún más hilos que este programa.
class A extends Thread {
public void run() {
System.out.println("**************started***************");
for(double i = 0.0; i < 500000000000000000.0; i++) {
System.gc();
System.out.println(Thread.currentThread().getName());
}
System.out.println("************************finished********************************");
}
}
public class Manager {
public static void main(String[] args) {
for(double j = 0.0; j < 50000000000.0; j++) {
A a = new A();
a.start();
}
}
}
main
arrojará un mensaje OutOfMemoryError
en mi máquina, diciendo que no puede crear más hilos. Quizás @AnilPal, no lo notaste. Sugiero incluir otra declaración de impresión en el main(..)
método, para ver claramente cuándo deja de crear nuevos hilos después de arrojar el error.