2008-10-23 12 views
117

¿Cuál es la diferencia entre usar un nuevo hilo y usar un hilo del grupo de hilos? ¿Qué beneficios de rendimiento existen y por qué debería considerar usar un hilo del grupo en lugar de uno creado explícitamente? Estoy pensando específicamente en .NET aquí, pero los ejemplos generales están bien.Thread vs ThreadPool

Respuesta

99

conjunto de subprocesos proporcionará beneficios para operaciones frecuentes y relativamente cortas por

  • La reutilización de las discusiones que ya han sido creadas en lugar de crear otros nuevos (un proceso costoso)
  • estrangulando el ritmo de creación de hilo cuando hay una explosión de solicitudes de nuevos elementos de trabajo (creo que esto es sólo en .NET 3,5)

    • Si te cola 100 tareas grupo de subprocesos, sólo usar tantos hilos como ya se han creado para dar servicio a estas solicitudes (digamos 10 por ejemplo). El grupo de subprocesos realizará comprobaciones frecuentes (creo que cada 500 ms en 3.5 SP1) y si hay tareas en cola, creará un nuevo subproceso. Si sus tareas son rápidas, entonces la cantidad de hilos nuevos será pequeña y reutilizar los 10 o más hilos para las tareas cortas será más rápido que crear 100 hilos por adelantado.

    • Si su carga de trabajo consistentemente tiene un gran número de solicitudes de grupo de subprocesos, el grupo de subprocesos se sintonizará a su carga de trabajo creando más subprocesos en el grupo mediante el proceso anterior para que haya un mayor número de subprocesos disponibles para procesar las solicitudes

    • cheque Here para obtener más información en profundidad sobre cómo funciona el grupo de subprocesos bajo el capó

Crear un nuevo hilo mismo habría más apr Si el trabajo iba a ser relativamente largo (probablemente alrededor de uno o dos segundos, pero depende de la situación específica)

@Krzysztof - Los subprocesos del hilo de fondo son hilos de fondo que se detendrán cuando termine el hilo principal. Los subprocesos creados manualmente están en primer plano de forma predeterminada (seguirán ejecutándose después de que el subproceso principal haya finalizado), pero se pueden establecer en segundo plano antes de llamar a Iniciar en ellos.

+5

Lo único que me gustaría saber es la siguiente declaración de MSDN (http://msdn.microsoft.com/en-us /library/1c9txz50.aspx) "Un hilo de fondo se ejecuta solo cuando la cantidad de hilos en primer plano que se ejecutan es menor que la cantidad de procesadores". Entonces, ¿eso significa que al dividir el trabajo entre núcleos, los hilos de primer plano tienen prioridad? – cdiggins

+1

➤ No puede cancelar o interrumpir un hilo del grupo de subprocesos. ➤ No puede unir un hilo del grupo de subprocesos. Para lograr eso, debe usar algunos otros mecanismos – Zinov

1

El almacenamiento local de subprocesos no es una buena idea con grupos de subprocesos. Le da a los hilos una "identidad"; no todos los hilos son iguales nunca más Ahora los grupos de subprocesos son especialmente útiles si solo necesitas un montón de subprocesos idénticos, listos para hacer tu trabajo sin gastos generales de creación.

1

Si necesita muchos subprocesos, es probable que desee utilizar un ThreadPool. Reutilizan subprocesos que le ahorran la sobrecarga de la creación de subprocesos.

Si solo necesita un hilo para hacer algo, el hilo probablemente sea el más fácil.

7

también

new Thread().Start()

desova hilo de primer plano que no morirá si cierra su programa. Los hilos ThreadPool son hilos de fondo que mueren al cerrar la aplicación.

+11

Siempre puede establecer un hilo en el fondo. Están en primer plano por defecto. –

+0

Eric, ¿cómo se hace eso? –

+3

nemo: var t = new Tema (...); t.BackgroundThread = true; t.Start(); –

0

En general (nunca he usado .NET), se usaría un grupo de subprocesos para la administración de recursos. Permite que las restricciones sean configuradas en su software. También se puede hacer por motivos de rendimiento, ya que la creación de nuevos hilos puede ser costosa.

También puede haber razones específicas del sistema. En Java (nuevamente no sé si esto se aplica a .NET), el administrador de los hilos puede aplicar variables específicas de subprocesos a medida que se extrae cada subproceso del grupo, y deshacerlos cuando se devuelven (forma común de pasar algo así como una identidad).

Restricción de ejemplo: Solo tengo 10 conexiones de db, por lo que solo permitiría 10 subprocesos de trabajo para acceder a la base de datos.

Esto no significa que no deba crear sus propios hilos, pero existen condiciones bajo las cuales tiene sentido usar un conjunto.

13

La administrado .NET subprocesos: -

  • Tamaños vez se basa en la carga de trabajo actual y hardware disponible
  • Contiene subprocesos de trabajo y hilos de puerto de finalización (que se utilizan específicamente para satisfacer IO)
  • Está optimizado para un gran número de operaciones relativamente efímeras

Otras implementaciones de agrupaciones de subprocesos ex Esto podría ser más apropiado para operaciones de larga ejecución.

Específicamente, use un grupo de subprocesos para evitar que su aplicación cree demasiados hilos. La característica más importante de un threadpool es la cola de trabajos. Es decir, una vez que su máquina está lo suficientemente ocupada, el grupo de subprocesos pondrá en cola las solicitudes en lugar de engendrar inmediatamente más subprocesos.

Por lo tanto, si crea un número pequeño y limitado de hilos, créelos usted mismo. Si no puede determinar por adelantado cuántos subprocesos se pueden crear (por ejemplo, se crearon en respuesta al IO entrante) y su trabajo será de corta duración, utilice el grupo de subprocesos. Si no sabe cuántos, pero su trabajo será de larga duración, no hay nada en la plataforma que lo ayude, pero es posible que pueda encontrar implementaciones de subprocesos alternativos que quepan.

+0

En .NET, ¿puede usar puertos completos sin el grupo de subprocesos? Estaba bajo el supuesto de que los métodos de E/S asíncronas eran la única forma (en .NET) y que usan el grupo de subprocesos – Karg

0

Usar una agrupación es una buena idea, si no sabe o no puede controlar cuántos subprocesos se crearán.

Tiene un problema con un formulario que utiliza subproceso para actualizar un campo de una base de datos en un evento de cambio de posición de un control de lista (evitar el freez). Mi usuario tardó 5 minutos en tener un error de la base de datos (demasiadas conexiones con Access) porque estaba cambiando la posición de la lista demasiado rápido ...

Sé que hay otra manera de resolver el problema base (incluidos no usar acceso) pero la puesta en común es un buen comienzo.

1

La necesidad principal de los subprocesos es tratar pequeñas tareas breves que se espera que se completen casi al instante. Los manejadores de interrupciones de hardware a menudo se ejecutan en un contexto de apilamiento que no sería adecuado para código no kernel, pero un controlador de interrupción de hardware puede descubrir que se debe ejecutar una devolución de llamada de finalización de E/S en modo usuario tan pronto como sea posible. Crear un nuevo hilo con el fin de ejecutar tal cosa sería una sobrecarga masiva. Tener algunos subprocesos creados previamente que pueden enviarse para ejecutar devoluciones de llamadas de finalización de E/S u otras cosas similares es mucho más eficiente.

Un aspecto clave de tales subprocesos es que si los métodos de finalización de E/S siempre se completan esencialmente instantáneamente y nunca se bloquean, y el número de subprocesos que están ejecutando tales métodos es al menos igual al número de procesadores, el único la forma en que podría ejecutar cualquier otro subproceso antes de que uno de los métodos antes mencionados termine sería si uno de los otros métodos bloquea o su tiempo de ejecución excede un intervalo de tiempo de subprocesamiento normal; ninguno de estos debería suceder muy a menudo si el grupo de subprocesos se usa como se pretendía.

Si no se puede esperar que un método salga dentro de los 100 ms aproximadamente de cuando comienza la ejecución, el método debe ejecutarse por algún otro medio que no sea el grupo de subprocesos principal. Si se tienen que realizar muchas tareas que consumen mucha CPU pero no se bloquean, puede ser útil enviarlas utilizando un conjunto de subprocesos de aplicaciones (uno por núcleo de CPU) que es independiente del grupo de subprocesos "principal", ya que más hilos que núcleos serán contraproducentes cuando se ejecutan tareas intensivas de CPU sin bloqueo. Sin embargo, si un método tardará un segundo o más en ejecutarse y pasará la mayor parte del tiempo bloqueado, es probable que el método se ejecute en un subproceso dedicado y, con seguridad, no se ejecute en un subproceso de subproceso principal. Si una operación de larga duración necesita ser activada por algo como una devolución de llamada de E/S, uno debe iniciar un hilo para la operación de larga ejecución antes de la devolución de llamada y esperar en un monitor que la devolución de llamada emita, o bien hacer que la devolución de llamada ejecute un nuevo hilo para realizar la operación mientras sale la devolución de llamada, devolviendo efectivamente su propio hilo al grupo de hilos.

2

Tenía curiosidad sobre el uso relativo de recursos para estos y ejecuté un punto de referencia en mi computadora portátil Intel i5 dual-core 2012 usando .NET 4.0 release build en Windows 8. Thread Pools tomó en promedio 0.035ms para comenzar donde Threads tomó un promedio de 5.06ms. En otras palabras, el hilo en el grupo comenzó aproximadamente 300 veces más rápido para un gran número de hilos de corta duración. Al menos en los hilos del rango probado (100-2000), el tiempo total por hilo parecía bastante constante.

Este es el código que fue punto de referencia:

for (int i = 0; i < ThreadCount; i++) { 
     Task.Run(() => { }); 
    } 

    for (int i = 0; i < ThreadCount; i++) { 
     var t = new Thread(() => { }); 
     t.Start(); 
    } 

enter image description here

+3

Creo que es porque el ThreadPool reutiliza los subprocesos creados en lugar de crear nuevos (lo que es mucho más caro)) – fabriciorissetto