Thread vs ThreadPool

137

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

Mark Ingram
fuente

Respuestas:

110

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

  • Reutilizar hilos que ya se han creado en lugar de crear nuevos (un proceso costoso)
  • Acelerar la tasa de creación de subprocesos cuando hay una explosión de solicitudes de nuevos elementos de trabajo (creo que esto es solo en .NET 3.5)

    • Si pone en cola 100 tareas de grupo de subprocesos, solo usará tantos subprocesos como se hayan creado para atender estas solicitudes (por ejemplo, 10). El grupo de subprocesos realizará verificaciones 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, la cantidad de subprocesos nuevos será pequeña y la reutilización de unos 10 subprocesos para las tareas cortas será más rápida que la creación de 100 subprocesos por adelantado.

    • Si su carga de trabajo consistentemente recibe un gran número de solicitudes de grupo de subprocesos, entonces el grupo de subprocesos se sintonizará con 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 solicitudes

    • consulte aquí para obtener información más detallada sobre cómo funciona el grupo de subprocesos bajo el capó

Crear un nuevo hilo usted mismo sería más apropiado si el trabajo fuera relativamente largo (probablemente alrededor de un segundo o dos, pero depende de la situación específica)

@Krzysztof: los subprocesos de grupo de subprocesos son subprocesos de fondo que se detendrán cuando finalice el subproceso 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.

Karg
fuente
55
Lo único que me pregunto es la siguiente declaración de MSDN ( msdn.microsoft.com/en-us/library/1c9txz50.aspx ) "Un subproceso en segundo plano se ejecuta solo cuando el número de subprocesos en primer plano en ejecución es menor que el número de procesadores ". Entonces, ¿eso significa que al dividir el trabajo entre núcleos los hilos de primer plano tienen prioridad?
cdiggins
1
➤ No puede abortar o interrumpir un hilo del grupo de hilos. ➤ No puedes unirte a un hilo del grupo de hilos. Para lograr eso, debe usar algunos otros mecanismos
Zinov
14

El conjunto de subprocesos administrado .NET: -

  • Se dimensiona en función de la carga de trabajo actual y el hardware disponible
  • Contiene subprocesos de trabajo y subprocesos de puerto de finalización (que se utilizan específicamente para dar servicio a IO)
  • Está optimizado para una gran cantidad de operaciones de corta duración.

Existen otras implementaciones de grupo de subprocesos que podrían ser más apropiadas para operaciones de larga duración.

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

Por lo tanto, si va a crear un número pequeño y limitado de hilos, créelos usted mismo. Si no puede determinar por adelantado cuántos subprocesos podrían crearse (por ejemplo, se crean en respuesta a las E / S entrantes), y su trabajo será de corta duración, use el conjunto 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 alternativas de agrupación de hilos que se ajusten.

Martín
fuente
En .NET, ¿puede usar puertos de finalización sin el grupo de subprocesos? Supuse que los métodos asíncronos de E / S eran la única forma (en .NET) y que usaban el grupo de subprocesos
Karg
10

además

new Thread().Start()

genera un subproceso en primer plano que no morirá si cierra su programa. Los hilos de ThreadPool son hilos de fondo que mueren cuando cierras la aplicación.


fuente
11
Siempre puede establecer un hilo en segundo plano. Son solo primer plano por defecto.
Kris Erickson el
3
nemo: var t = nuevo hilo (...); t.BackgroundThread = true; t.Start ();
Ricardo Amores
18
Aclaración sobre el término "programa". Una aplicación de escritorio se ejecuta en un proceso y tiene al menos un subproceso en primer plano que administra la IU. Ese proceso continuará ejecutándose mientras tenga subprocesos en primer plano. Cuando cierra una aplicación de escritorio, el subproceso de interfaz de usuario en primer plano se detiene, pero no necesariamente ha detenido el proceso si tiene otros subprocesos en primer plano.
G-Wiz
8

Tenía curiosidad sobre el uso relativo de recursos para estos y ejecuté un punto de referencia en mi computadora portátil Intel i5 de doble núcleo de 2012 usando la compilación de lanzamiento .net 4.0 en Windows 8. Los grupos de subprocesos tomaron un promedio de 0.035 ms para comenzar donde los subprocesos tomaron un promedio de 5.06 em. En otras palabras, el subproceso en el grupo comenzó aproximadamente 300 veces más rápido para grandes cantidades de subprocesos de corta duración. Al menos en el rango probado (100-2000) subprocesos, el tiempo total por subproceso parecía bastante constante.

Este es el código que fue comparado:

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

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

ingrese la descripción de la imagen aquí

PeterM
fuente
55
Creo que es debido a que el ThreadPool reutilizar los hilos creados en lugar de crear otros nuevos (lo que es mucho más caro)
fabriciorissetto
1

El almacenamiento local de subprocesos no es una buena idea con los grupos de subprocesos. Le da a los hilos una "identidad"; ya no todos los hilos son iguales. Ahora los grupos de subprocesos son especialmente útiles si solo necesita un montón de subprocesos idénticos, listos para hacer su trabajo sin sobrecarga de creación.

MSalters
fuente
1

Si necesita muchos hilos, probablemente quiera usar un ThreadPool. Reutilizan hilos ahorrándote la sobrecarga de creación de hilos.

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

Rob Prouse
fuente
1

La necesidad principal de los subprocesos de agrupación es manejar pequeñas tareas cortas que se espera que se completen casi instantáneamente. Los controladores de interrupción de hardware a menudo se ejecutan en un contexto de apilamiento que no sería adecuado para el código que no es del núcleo, pero un controlador de interrupción de hardware puede descubrir que una devolución de llamada de finalización de E / S en modo de usuario debe ejecutarse lo antes posible. Crear un nuevo hilo con el fin de ejecutar tal cosa sería una exageración masiva. Tener algunos subprocesos creados previamente que se pueden enviar para ejecutar devoluciones de llamada 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 de manera instantánea y nunca se bloquean, y el número de subprocesos que actualmente ejecutan dichos métodos es al menos igual al número de procesadores, la única forma en que cualquier otro subproceso podría ejecutarse antes de que finalice uno de los métodos mencionados anteriormente si uno de los otros bloques de métodos o su tiempo de ejecución supera un intervalo de tiempo de subprocesamiento normal; ninguno de estos debería suceder muy a menudo si el grupo de subprocesos se utiliza según lo previsto.

Si no se puede esperar que un método salga dentro de los 100 ms aproximadamente cuando comienza la ejecución, el método debe ejecutarse por algún otro medio que no sea el grupo de subprocesos principal. Si tiene muchas tareas que realizar que requieren un uso intensivo de la CPU pero no se bloquean, puede ser útil enviarlas utilizando un conjunto de subprocesos de aplicación (uno por núcleo de CPU) que está separado del conjunto de subprocesos "principal", ya que más subprocesos que núcleos serán contraproducentes al ejecutar 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 de su tiempo bloqueado, es probable que el método se ejecute en un subproceso dedicado y casi seguro que no se ejecute en un subproceso de conjunto de subprocesos principales. Si una operación de larga duración necesita ser activada por algo como una devolución de llamada de E / S,

Super gato
fuente
0

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

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

Restricción de ejemplo: solo tengo conexiones de 10 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 subprocesos, pero hay condiciones bajo las cuales tiene sentido usar un grupo.

Robin
fuente
0

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

Simplemente tenga un problema con un formulario que usa hilo para actualizar algún campo de una base de datos en un evento de cambio de posición de un control de lista (evite congelar). A mi usuario le tomó 5 minutos tener un error de la base de datos (demasiada conexión con Access) porque estaba cambiando la posición de la lista demasiado rápido ...

Sé que hay otra forma de resolver el problema base (incluyendo no usar el acceso), pero la agrupación es un buen comienzo.

Marco Guignard
fuente
0

Hilo :

  1. Crear un subproceso es mucho más lento que usar el conjunto de subprocesos.
  2. Puede cambiar la prioridad de un hilo.
  3. El número máximo de subprocesos en un proceso relacionado con los recursos.
  4. El hilo está en el nivel del sistema operativo y controlado por el sistema operativo.
  5. Usar Thread es una mejor opción cuando la tarea es relativamente larga

Thread-Pool :

  1. Ejecutar un subproceso en el grupo de subprocesos es mucho más rápido que crear directamente un subproceso.
  2. No puede cambiar la prioridad de una ejecución de subproceso basada en Thread-pool.
  3. Solo hay un grupo de subprocesos por proceso.
  4. El grupo de subprocesos es administrado por CLR.
  5. El grupo de subprocesos es útil para operaciones de corta duración.
  6. El número de subprocesos en el grupo de subprocesos está relacionado con la carga de la aplicación.
  7. Las tareas de TPL se ejecutan en base a Thread-pool
Seyedraouf Modarresi
fuente