Thread poolUn thread pool in programmazione indica un gestore software di thread utilizzato per ottimizzare e semplificare l'utilizzo dei thread all'interno di un programma. Funzionamento generaleDurante la stesura di un programma è possibile, con diversi metodi, sottomettere dei task (o compiti) da eseguire al thread pool. Sarà compito del thread pool affidare il task ad un thread. Un concetto ricorrente nei thread pool è il riutilizzo dei thread: un thread viene usato più volte per diversi task durante il suo ciclo di vita. Questo diminuisce l'overhead dovuto alla creazione dei thread e incrementa le prestazioni del programma che sfrutta il thread pool. Il riutilizzo dei thread non è una regola, ma è uno dei principali motivi che portano un programmatore a utilizzare un thread pool nei suoi applicativi. Implementazione e funzionamentoUna implementazione di thread pool è composta di solito da una coda di task e da un insieme di thread, entrambi inizialmente vuoti.
Una volta che il thread pool è stato inizializzato, è possibile richiedere che vengano creati subito i thread minimi, cioè quelli che rimarrebbero in vita anche in assenza di task[2]. Spesso viene sfruttata questa funzione se si prevede un utilizzo intensivo del thread pool e si vuole una certa reattività nell'esecuzione dei task. Implementazioni differenti potrebbero prevedere comportamenti diversi, ma lo schema generico è quello presentato finora. VantaggiUtilizzare un thread pool nativo o implementato in una particolare architettura comporta un incremento di prestazioni da parte delle applicazioni che lo sfruttano: i thread pool ottimizzano l'utilizzo della memoria e del processore, diminuendo l'overhead di gestione dei thread. È possibile comunque adeguare il thread pool alle proprie esigenze, nel caso i parametri standard non siano soddisfacenti. Oltretutto la parallelizzazione di alcune operazioni porta ad un'ottimizzazione delle risorse e ad un incremento di velocità nello svolgimento dei compiti, anche se introduce altri tipi di problemi come l'accesso esclusivo a risorse condivise (problema di race condition). Architetture che utilizzano i thread poolI thread pool sono utilizzati in quasi tutte le applicazioni server, in cui c'è l'esigenza di trattare più richieste contemporanee da parte di un numero imprecisato di client. Linguaggi che implementano i thread pool
EsempiDi seguito sono riportati alcuni esempi di utilizzo dei thread pool nei principali linguaggi di programmazione che li supportano nativamente. Javaimport java.util.concurrent.Executors;
import java.util.concurrent.ExecutorService;
public class Esempio {
public static void main(String[ ] args) {
//Creo un nuovo thread pool.
ExecutorService threadpool = Executors.newCachedThreadPool();
//Metto in coda il task
threadpool.execute(
//Questo oggetto rappresenta il task.
new Runnable() {
public void run() {
System.out.println("Vengo eseguito dal thread pool.");
}
});
System.out.println("Il thread principale prosegue e poi si mette in attesa.");
threadpool.shutdown();
System.out.println("Il thread principale esce.");
}
}
Visual Basic .NETImports System
Imports System.Threading
Public Class Example
<MTAThread> _
Public Shared Sub Main()
' Metto in coda il task.
ThreadPool.QueueUserWorkItem( _
New WaitCallback(AddressOf ThreadProc) _
)
Console.WriteLine("Il thread principale prosegue e poi si mette in attesa.")
Thread.Sleep(1000)
Console.WriteLine("Il thread principale esce.")
End Sub
' Questa procedura rappresenta il task.
Shared Sub ThreadProc(stateInfo As Object)
Console.WriteLine("Vengo eseguito dal thread pool.")
End Sub
End Class
C# .NETusing System;
using System.Threading;
public class Example {
public static void Main() {
// Metto in coda il task.
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));
Console.WriteLine("Il thread principale prosegue e poi si mette in attesa.");
Thread.Sleep(1000);
Console.WriteLine("Il thread principale esce.");
}
// Questa procedura rappresenta il task.
static void ThreadProc(Object stateInfo) {
Console.WriteLine("Vengo eseguito dal thread pool.");
}
}
C++ .NETusing namespace System;
using namespace System::Threading;
ref class Example
{
public:
// Questa procedura rappresenta il task.
static void ThreadProc( Object^ stateInfo )
{
Console::WriteLine( "Vengo eseguito dal thread pool." );
}
};
int main()
{
// Metto in coda il task.
ThreadPool::QueueUserWorkItem( gcnew WaitCallback( Example::ThreadProc ) );
Console::WriteLine( "Il thread principale prosegue e poi si mette in attesa." );
Thread::Sleep( 1000 );
Console::WriteLine( "Il thread principale esce." );
return 0;
}
J# .NETimport System.*;
import System.Threading.*;
import System.Threading.Thread;
public class Example
{
public static void main(String[] args)
{
// Metto in coda il task.
ThreadPool.QueueUserWorkItem(new WaitCallback(ThreadProc));
Console.WriteLine("Il thread principale prosegue e poi si mette in attesa.");
Thread.Sleep(1000);
Console.WriteLine("Il thread principale esce.");
} //main
// Questa procedura rappresenta il task.
static void ThreadProc(Object stateInfo)
{
Console.WriteLine("Vengo eseguito dal thread pool.");
} //ThreadProc
} //Example
Note
Voci correlateCollegamenti esterni
|