Nu rare sunt cazurile in care avem o lista de taskuri de executat si executia fiecarui task, unul cate unul, pe masura ce taskul curent se termina e o operatie ineficienta prin faptul ca e lenta.
De exemplu, daca am de facut o verificare in urma careia sa stabilim daca anumite pagini web sunt sau nu online – sa presupunem ca avem anunturi/bannere puse acolo. Asta inseamna ca am o lista de 1000 url-uri si vreau sa verific pentru fiecare daca bannerul meu mai apare pe acolo, daca pagina mai est online etc.
Astazi voi descrie numai procesul, algoritmul pe care o sa il folosesc, urmand ca in zilele urmatoare sa creez o aplicatie simpla care sa implementeze ceea ce prezint astazi. S-ar putea sa existe si solutii mai eficiente decat ceea pe care o prezint eu, insa nu mi-a venit alta in minte in momentul in care am avut nevoie.
Voi pune toate linkurile intr-o lista: List
Asta ar trebui sa arate cam asa:

Pentru a eficientizaoperatia ar trebui sa citim cate un numar X de linkuri in acelasi timp. Nu pot, pur si simplu, sa scriu un ciclu for si sa creez un thread pentru fiecare link din lista, deoarece as avea 1000 de threaduri care ar rula in acelasi timp, ceea ce nu e prea bine. As vrea sa limitez numarul de fire de executie la X (in caul meu am decis ca X sa fie 10). Pe masura ce un fir de executie isi termina executia, se verifica lista de waiting si, dca aceasta mai contine linkuri, se creeaza si ruleaza un nou thread cu respectivul link. Programul isi termina executia in momentul in care waitingList si inWork sunt goale. Se salveaza lista status si se termina executia programului.
Suna simplu, insa nu e chiar asa de simplu. Cum as rezolva eu aceasta problema? Cam asa:
Am nevoie de un thread care sa aiba un loop infinit, care sa joace rolul de “manager”. Acest thread va coordona un anumit numar de threaduri (X). Fiecare thread va executa operatia de citire + analizare a unui url. Cand un thread isi termina executia (sau depaseste timpul alocat rularii – timeout) un nou thread este pornit, daca mai exista linkuri in lista de waiting. Cand listele waitingList si inWork sunt goale threadul manager isi incheie existenta, la fel ca si intregul program. Pare simplu, nu? Cum ar arata asta in pseudocod? Asa:
initializare: waitingList, inWork, statusList
int maxParalelThreads = 10
metoda main()
{
initializare: listaRunningThreads
citeste lista linkuri -> waitingList
while(true)
{
daca waitingList==empty && inWork == empty break;
daca listaRunningThreads.Count < maxParalelThreads
{
pornesteThreadNou(t)
adaoga t in listaRunningThreads
}
verifica listaRunningThreads
{
elimina threads terminate
elimina din inWork linkurile analizate in threadul terminat
pune in statusList analiza din threadul terminat
}
}
Salveaza statusList in fisier //afiseaza, trimite in mail etc
print "Terminat."
}
Citirea continutului unei pagini web este o operatie lenta, care depinde de diversi factori pe care programatorul nu ii poate controla. Din aceasta cauza rularea in mai multe thread-uri a peratiilor de citire vor imbunatati foarte mult timpul de executie al intregii aplicatii. Daca citirea s-ar fi facut in ordine, asteptand initializarea urmatoarei citiri pana la terminarea citirii in executie, timpul de rulare al aplicatiei ar fi putut ajunge si pana la de X ori mai lung (X e numarul de threaduri folosite) decat in varianta cu threaduri.
Alte aplicatii care pot fi imbunatatite prin tehnici similare: scrierea in loguri, trimiterea de cereri la baze de date, preluarea datelor din webservices etc.