Grupe niti
Sve niti u Javi su grupisane u grupe niti, bez obzira da li to eksplicitno navedete ili ne. U Javi postoji klasa ThreadGroup koja vam dozvoljava i da sami napravite svoju grupu niti. Ova klasa olakšava upravljanje i kontrolisanje nekoliko niti odjednom. Ona takođe ima metode stop(), suspend() i resume(), ali oni kontrolišu izvršavanje svih niti u grupi. Svaka grupa niti može da sadrži druge grupe (podgrupe), pa se na taj način obezbeđuje hijerarhija niti. Takođe, korišćenje grupa niti je dobro i sa stanovišta sigurnosti.
Klasa Thread ima tri konstruktora pomoću kojih možete da kreirate nit koja pripada odgovarajućoj grupi:
Thread(ThreadGroup, Runnable);
Thread(ThreadGroup, String);
Thread(ThreadGroup, Runnable, String);
Na primer, sledeći kod koji kreira grupu niti osnovnaGrupa. Nakon kreiranja grupe, kreiraju se niti koje joj pripadaju:
ThreadGroup osnovnaGrupa = new ThreadGroup("Grupa niti");
Thread t1 = new Thread(osnovnaGrupa, this);
Thread t2 = new Thread(osnovnaGrupa, this);
Thread t3 = new Thread(osnovnaGrupa, this);
Podrazumeva se da niti koje kreirate nemaju specifičan nivo zaštite. Kao rezultat toga, bilo koja nit iz grupe može slobodno da pristupa i modifikuje niti iz drugih grupa. Međutim, korišćenjem apstraktne klase SecurityManager možete da dodelite zabranu pristupa grupama niti.
Raspored izvršavanja niti
Ukoliko na sistemu na kome se program izvršava postoji samo jedan procesor, nemoguće ja da više od jedne instrukcije bude izvršeno istovremeno. U suštini, uvek se samo jedna nit izvršava u određenom trenutku. Iluzija o paralelnom izvršavanju se postiže tako što se svakoj niti dodeljuje podjednak interval vremena za izvršavanje dela koda. Frekvencija smenjivanja ovih intervala je velika, pa se dobija utisak o paralelnom radu.
Raspoređivanje niti (vremena izvršavanja) vrši se sistemski. Moguće su dve vrste rasporeda: preventivan i ne-preventivan. Kod ne-preventivnog raspoređivanja, tekuća nit se izvršava proizvoljno dugo i zahteva se da ta nit sama da signal kada je sigurno da neka druga nit krene da se izvršava. Kod preventivnog raspoređivanja, jedna nit se izvršava u određenom, malom vremenskom intervalu, a zatim se suspenduje i dodeljuje se novi vremenski interval za sledeću nit. Ne-preventivno raspoređivanje je od velikog značaja za vremenski kritične aplikacije gde prekidanje niti u nezgodnom trenutku može da prouzrokuje veliku štetu. Većina modernih sistema koristi preventivnu podelu vremena. Ova činjenica čini pisanje programa jednostavnijim, ali često upravo taj nedostatak kontrole nad izvršavanjem niti ume i da oteža programiranje. Zbog toga je u većini sistema moguće nitima dodeliti prioritete. Ovo neke niti čini važnijim od drugih. Ukoliko je nit višeg prioriteta to znači da joj se češće dodeljuje vreme za izvršavanje ili da joj se dodeljuje više vremena, ali i da ona može da prekine druge niti nižeg prioriteta.
Dobar primer niti sa niskim prioritetom jeste garbage collector. Iako je on jako važan u Java platformi, svakako ne želite da vam on uzurpira procesorsko vreme.
Da biste saznali kako se niti raspoređuju na vašem sistemu možete da pokrenete sledeći program:
public class Nit implements Runnable {
public void run() {
while (true)
System.out.println(
Thread.currentThread().getName());
}
}
public class TesterRasporedjivanja {
public static void main (String arg[]) {
Nit nit1 = new Nit();
new Thread(nit1, “jedan”).start();
new Thread(nit1, “dva”).start();
}
}
Ukoliko je na sistemu na kome se ovaj program izvršava raspoređivanje vremena procesora nepreventivno, rezultat će biti sledeći:
jedan
jedan
jedan
.......
Ukoliko je raspoređivanje preventivno, rezultat će biti
jedan
jedan
jedan
.......
dva
dva
dva
........
Ukoliko želite da postignete da se niti izvršavaju naizmenično, bez obzira na tip raspoređivanja, klasa Nit bi trebala da izgleda ovako:
public class Nit implements Runnable {
public void run() {
while (true) {
System.out.println(
Thread.currentThread().getName());
Thread.yield(); //dozvoljava drugoj niti da se izvrsi
}
}
}
Metod yield() eksplicitno dozvoljava drugoj niti da počne da se izvršava. Ukoliko sada pokrenete prethodni program, rezultat će biti sledeći:
jedan
dva
jedan
dva
jedan
.........
Dodeljivanje prioriteta
Jedna nit može da ima tri prioriteta: nizak, normalan i visok. Unutar klase Thread postoje konstante koje odgovaraju ovim prioritetima:Thread.MIN_PRIORITY, Thread.NORM_PRIORITY i Thread.MAX_PRIORITY. Prioriteti u Javi su u rasponu od 1 do 10, pri čemu vrednost 5 odgovara normalnom prioritetu.
Pogledajte sledeći primer:
public class TesterPrioriteta {
public static void main(String arg[]) {
Nit nit1 = new Nit();
Thread t1 = new Thread(nit1, “jedan”);
Thread t2 = new Thread(nit1, “dva”);
t2.setPriority(t1.getPriority() +1);
t1.start();
t2.start(); // po prioritetu Thread.NORM_PRIORITY + 1
}
}
Bez obzira što se prvo pokreće nit t1, niti t2 je dodeljen prioritet za 1 veći od prioriteta niti t1, pa će nit t2 prekinuti izvršavanje niti t1. Ukoliko koristite varijantu klase Nit bez yield() metoda, nit t2 će se izvršavati beskonačno, dok nit t1 neće ni dobiti priliku da se izvrši.