2012-03-01 17 views
6

Tengo una gran cantidad de tareas para ejecutar con multithreading.¿Cómo administrar la memoria cuando se utiliza ExecutorService?

uso el ExecutorService a presentar un montón de Callable objects, y cada Callable object contiene algunos resource que es necesaria para la ejecución.

Problema

Estas tareas son tantos que la Callable objects presentado a ExecutorService ocupan demasiada memoria, entonces el heap se agota.

Quiero saber, ¿cuándo el JVM libera el espacio para estos Callable objects?

¿Hace esto inmediatamente después de que se realiza la tarea y cómo podría administrar la memoria utilizada para ExecutorService?

Quiero controlar el envío a ExecutorService, por ejemplo, cuando la memoria no es suficiente, bloquee el envío de algunas tareas completadas y espacio libre. ¿Podría?


El código completo es demasiado complicado, adjuntaré el marco principal de mi código.

public class MyCallable implements Callable<Result> { 

    ... // Some members 

    public MyCallable(...) { 
    ... 
    } 

    @Override 
    public Result call() throws Exception { 
    ... // Doing the task 
    } 
} 

class MyFutureTask extends FutureTask<Result> { 

    ... // Some members 

    public MyFutureTask(...) { 
    super(new MyCallable(...)); 
    } 

    @Override 
    public void done() { 
    Result result = get(); 
    ... // Something to do immediately after the task is done 
    } 
} 

// Here is the code to add tasks 
ExecutorService executor = Executors.newFixedThreadPool(threadPoolSize); 
while (...) { 
    ... // Reading some data from files 
    executor.submit(new MatchFutureTask(...)); 
} 
executor.shutdown(); 
+0

una respuesta a su problema se puede dar si se añade un fragmento de código. ¿Qué tipo de servicio ejecutor estás usando? ¿Qué significan muchos (es decir, cuántos son muchos)? –

+0

PD: tengo la sensación de que en realidad estás enfrentando un problema de pérdida de memoria (supongo que en alguna otra parte de tu aplicación tienes referencias a tus Callables) y no un problema de servicio del ejecutor. –

+0

@AlexCalugarescu Uso Executors.newFixedThreadPool() para crear ExecuteService, por lo que debe ser ThreadPoolExecutor. Y los "muchos" significan, el archivo de texto original tiene más de 3GB, lo leo y me encubro a algunos objetos para almacenar en Callables, así que creo que son demasiados. – Auguste

Respuesta

3

El método Runtime.getRuntime().freeMemory() le dirá la cantidad de memoria libre que tiene la JVM. Puede escribir una implementación de ThreadFactory que compruebe este valor antes de crear un nuevo hilo.

+0

no hay problema Estoy frente pero brillante respuesta +1. – Shahzeb

6

Si está utilizando el ExecutorService, debe pasar un BlockingQueue al constructor, ¿no? Supongo que estás usando un ThreadPoolExecutor. Utilice una ArrayBlockingQueue con una capacidad fija, y pase ThreadPoolExecutor.CallerRunsPolicy al constructor de ThreadPoolExecutor. Esto limitará bastante efectivamente su tasa de envío si establece el valor máximo de Poolsize en algún valor razonable.

Para responder a su primera pregunta, la VM liberará la memoria "en algún momento después" de que ya no haya referencias a los objetos. Si el Callable es autónomo en términos de estado, una vez que se termine de ejecutar, la VM debe recolectarlo antes de causarle un error de falta de memoria.

+0

Bueno, solo uso Executors.newFixedThreadPool() para crear ExecuteService, así que no pasé un BlockingQueue. ¿Qué hace BlockingQueue? – Auguste

+0

Un BlockingQueue solo permitirá que se ponga en cola una cantidad específica de tareas en el ejecutor. Executors.newFixedThreadPool() permitirá un número ilimitado de tareas. – brettw

+2

Creo que lo resuelvo.Cambio para crear el objeto ThreadPoolExecutor por mí mismo, lo que realmente podría controlar el tamaño de la cola de tareas en espera. ¡Muchas gracias! – Auguste

2

parecía que el uso de Executors.newCachedThreadPool() de memoria reducido en un 30% - 60%

Cuestiones relacionadas