ThreadPoolExecutor - 1

"I programmatori ordinari prima o poi fanno i conti con il fatto che hanno molti piccoli compiti che devono essere eseguiti di tanto in tanto."

"Se stai scrivendo un gioco, allora sono le azioni che compiono i singoli personaggi."

"Se stai scrivendo un server web, sono diversi i comandi che arrivano dagli utenti: carica una foto, transcodificala nel formato desiderato, applica il modello desiderato, ecc."

"Prima o poi, tutte le grandi attività vengono suddivise in una serie di piccole attività gestibili."

"Quindi, dato questo contesto, sorge una domanda sottile: come dovresti gestirli tutti? E ​​se avessi bisogno di eseguire diverse centinaia di attività in un minuto? Creare un thread per ogni attività non avrebbe molto senso. La macchina Java alloca molte risorse per ogni thread."

"In altre parole, la creazione e la distruzione di un thread possono richiedere più tempo e risorse rispetto all'attività stessa."

"I creatori di Java hanno trovato una soluzione elegante a questo problema: ThreadPoolExecutor .

" ThreadPoolExecutor è una classe con due cose all'interno:"

A)  Una coda di attività, a cui è possibile aggiungere attività man mano che si presentano nel programma.

B) Un pool di thread, ovvero un gruppo di thread che eseguono queste attività.

"Inoltre, i thread non vengono distrutti una volta che un'attività è terminata. Invece, si addormentano per essere pronti a iniziare una nuova attività non appena appare."

"Quando crei un ThreadPoolExecutor , puoi impostare il numero massimo di thread da creare e il numero massimo di attività che possono essere accodate. In altre parole, puoi limitare il numero di thread a 10, ad esempio, e il numero di attività in coda a 100."

"Ecco come funziona ThreadPoolExecutor :"

1)  Quando aggiungi una nuova attività, questa viene posizionata alla fine della coda.

2)  Se la coda è piena, viene generata un'eccezione.

3)  Dopo aver completato un'attività, ogni thread prende l'attività successiva dalla coda e inizia a eseguirla.

4) Se non ci sono attività in coda, un thread va in sospensione fino a quando non vengono aggiunte nuove attività.

"L'approccio, in cui limitiamo il numero di thread di lavoro, è vantaggioso in quanto più thread abbiamo, più interferiscono tra loro. È molto più efficace avere 5-10 thread di lavoro e una lunga coda di attività rispetto creare 100 thread per un'ondata di attività, che competeranno tra loro per le risorse: memoria, tempo del processore, accesso al database, ecc."

"Ecco un esempio di ThreadPoolExecutor in azione:"

Esempio
ExecutorService service = Executors.newFixedThreadPool(2);

for(int i = 0; i < 10; i++)
{
 service.submit(new Runnable() {
    public void run()
    {
     // Here we download something big from the Internet.
    }
 });
}

"Ehm, non lo vedo..."

"Un oggetto ThreadPoolExecutor viene creato quando viene chiamato il metodo newFixedThreadPool."

Quindi, è molto facile da usare. Non appena aggiungi un'attività con il metodo submit, essa:

A)  Riattiva un thread dormiente, se ce n'è uno, per eseguire l'attività.

B)  Se non ci sono thread in attesa, ne crea uno nuovo per l'attività.

C)  Se viene raggiunto il numero massimo di thread, inserisce semplicemente l'attività alla fine della coda.

"Ho deliberatamente incluso nell'esempio «qui scarichiamo qualcosa di grosso da Internet». Se abbiamo 100 compiti «scarica qualcosa di grosso da Internet», allora non ha senso eseguirne molti contemporaneamente: noi' sarò trattenuto dal limite di larghezza di banda della nostra connessione Internet. In questo caso, un paio di thread dovrebbero essere sufficienti. Questo è ciò che vedi nell'esempio sopra:"

ExecutorService service = Executors.newFixedThreadPool(2);

"Si scopre che lavorare con una serie di attività non è così difficile."

"Sì. Ancora più facile di quanto tu possa immaginare. Ma Kim te lo dirà."