2011-03-08 12 views
6

Tengo una aplicación de subprocesos múltiples. Al usar Thread.start() para iniciar manualmente los hilos, cada hilo concurrente usa exactamente un 25% de CPU (o exactamente un núcleo, esto es en una máquina de cuatro núcleos). Entonces, si uso dos hilos, el uso de la CPU es exactamente del 50%.Java: ExecutorService menos eficiente que las ejecuciones de subprocesos manuales?

Sin embargo, cuando se utiliza ExecutorService para ejecutar subprocesos, parece haber un hilo "fantasma" que consume recursos de la CPU. Un hilo utiliza el 50% en lugar del 25%, el uso de dos hilos el 75%, etc.

¿Podría ser este un tipo de artefacto del administrador de tareas de Windows?

Excutor código de servicio es

ExecutorService executor = Executors.newFixedThreadPool(threadAmount); 

for (int i = 1; i < 50; i++) { 
    Runnable worker = new ActualThread(i); 
    executor.execute(worker); 
} 
executor.shutdown(); 
while (!executor.isTerminated()) { 

} 
System.out.println("Finished all threads"); 

y el código hilo.start() es:

ActualThread one= new ActualThread(2,3); 
ActualThread two= new ActualThread(3,4); 
... 

Thread threadOne = new Thread(one); 
Thread threadTtwo = new Thread(two); 
... 

threadOne.start(); 
threadTwo.start(); 
... 
+1

¿Dónde está el código para esperar a que los hilos terminen en el segundo ejemplo? –

Respuesta

16

Aquí es su problema:

while (!executor.isTerminated()) { 

} 

Su método "principal" está girando la CPU no haciendo nada. Use invokeAll() en su lugar, y su hilo se bloqueará sin una espera ocupada.

final ExecutorService executor = Executors.newFixedThreadPool(threadAmount); 
final List<Callable<Object>> tasks = new ArrayList<Callable<Object>>(); 

for (int i = 1; i < 50; i++) { 
    tasks.add(Executors.callable(new ActualThread(i))); 
} 
executor.invokeAll(tasks); 
executor.shutdown(); // not really necessary if the executor goes out of scope. 
System.out.println("Finished all threads"); 

Desde invokeAll() quiere una colección de Callable, tenga en cuenta el uso del método de ayuda Executors.callable(). De hecho, puede usar esto para obtener una colección de Future s para las tareas, lo que es útil si las tareas realmente están produciendo algo que desea como resultado.

+1

+1, un cambio un poco más pequeño sería usar 'awaitTermination'. –

+0

@Mark, sí, pero ¿por qué las acrobacias manuales cuando 'invokeAll()' está ahí para ti? Este modelo también fomenta la reutilización del ejecutor, lo que a menudo es algo bueno ... en cualquier caso, cualquiera de los dos funciona. – andersoj

Cuestiones relacionadas