programacion - ¿Por qué mi programa Java pierde memoria cuando llamo a ejecutar() en un objeto Thread?
mover figuras geometricas en java (3)
Dudo que la construcción de una instancia de un subproceso o una subclase del mismo derrame memoria. En primer lugar, no hay nada de los géneros mencionados en los Javadocs o en la Especificación del lenguaje Java. En segundo lugar, realicé una prueba simple y también muestra que no se ha filtrado ninguna memoria (al menos, no en Sun''s JDK 1.5.0_05 en 32-bit x86 Linux 2.6):
public final class Test {
public static final void main(String[] params) throws Exception {
final Runtime rt = Runtime.getRuntime();
long i = 0;
while(true) {
new MyThread().run();
i++;
if ((i % 100) == 0) {
System.out.println((i / 100) + ": " + (rt.freeMemory() / 1024 / 1024) + " " + (rt.totalMemory() / 1024 / 1024));
}
}
}
static class MyThread extends Thread {
private final byte[] tmp = new byte[10 * 1024 * 1024];
public void run() {
System.out.print(".");
}
}
}
EDITAR: Solo para resumir la idea de la prueba anterior. Cada instancia de la subclase MyThread de un subproceso hace referencia a su propia matriz de 10 MB. Si las instancias de MyThread no se recogieron basura, la JVM se quedaría sin memoria muy rápidamente. Sin embargo, ejecutar el código de prueba muestra que la JVM está usando una pequeña cantidad de memoria constante, independientemente del número de MyThreads construidos hasta el momento. Reclamo que esto se debe a que las instancias de MyThread son basura.
(Pregunta al estilo Jeopardy, desearía que la respuesta hubiera estado en línea cuando tuve este problema)
Usando Java 1.4, tengo un método que quiero ejecutar como hilo de vez en cuando, pero no en otros. Así que lo declare como una subclase de Thread, luego o bien se llama start () o run () según lo que necesite.
Pero descubrí que mi programa perderá memoria con el tiempo. ¿Qué estoy haciendo mal?
Veamos si podríamos acercarnos al núcleo del problema:
Si inicia su programa (digamos) 1000 x usando start (), entonces 1000 x usando run () en un hilo, ¿ambas memorias están sueltas? Si es así, entonces su algoritmo debe ser revisado (es decir, para objetos externos tales como Vectores usados en su Runnable).
Si no hay tal pérdida de memoria como se describió anteriormente, entonces debe investigar acerca de los parámetros de inicio y el uso de la memoria de los hilos con respecto a la JVM.
Este es un error conocido en Java 1.4: http://bugs.sun.com/bugdatabase/view_bug.do;jsessionid=5869e03fee226ffffffffc40d4fa881a86e3:WuuT?bug_id=4533087
Está arreglado en Java 1.5 pero Sun no tiene la intención de arreglarlo en 1.4.
El problema es que, en el momento de la construcción, se agrega un Thread
a una lista de referencias en una tabla de subprocesos internos. No se eliminará de esa lista hasta que se complete su método start (). Mientras esa referencia esté allí, no se recolectará basura.
Por lo tanto, nunca cree un hilo a menos que definitivamente llame a su método start()
. El método run()
un objeto Thread
no debe invocarse directamente.
Una mejor forma de codificarlo es implementar la interfaz Runnable
en lugar de la subclase Thread
. Cuando no necesitas un hilo, llama
myRunnable.run();
Cuando necesitas un hilo:
Thread myThread = new Thread(myRunnable);
myThread.start();