Fire de execuție in Java
Implementarea unui nou thread
În Java există două modalități prin care putem să implementăm un nou thread.
Prima variantă de implementare are la bază crearea unei clase ce implementează interfața Runnable ce conține metoda void run(). Codul ce va reprezenta logica noului thread va fi plasat în interiorul acestei metode.
public class Task implements Runnable {
public void run() {
System.out.println("Hello from my new thread!");
}
}
O altă metodă de implementare a unui thread constă din crearea unei clase ce extinde clasa Thread și suprascrie (overrides) metoda void run() din cadrul acesteia. La fel ca în primul caz, logica noului thread va fi implementată în cadrul acestei metode.
public class MyThread extends Thread {
public void run() {
System.out.println("Hello from my new thread!");
}
}
Rularea în paralel a noului thread
În cazul în care s-a folosit mecanismul de implementare a interfeței Runnable, atunci pentru a putea crea un thread nou ce va conține logica definită în clasa Task se va crea o instanță a clasei Task ce va fi furnizată ca parametru constructorului clasei Thread. Pentru a rula în paralel noul thread creat cu ajutorul constructorului se va apela metoda public void start() a acestuia.
public class Main {
public static void main(String[] args) {
Thread t = new Thread(new Task());
t.start();
}
}
În cazul în care s-a extins clasa Thread pentru implementarea noului tip de thread, se va putea crea un thread nou prin instanțierea directă a clasei MyThread și, pentru a se porni excecuția în paralel a acestuia, se va apela metoda public void start() moștenită din cadrul clasei Thread.
public class Main {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
}
}
Există o distincție foarte importantă între metodele de start() și run() ale clasei Thread! Atunci când este apelată metoda run(), codul prezent în aceasta se va executa secvențial în cadrul thread-ului care a apelat-o. Atunci când este apelată metoda start(), JVM (Java Virtual Machine) va crea un nou thread ce va executa instrucțiunile prezente în cadrul metodei run() în paralel cu thread-ul care a apelat metoda start().
Așteptarea terminării execuției unui thread
Pentru a aștepta terminarea execuției unui thread, Java ne pune la dispoziție metoda public final void join() a clasei Thread. Trebuie ținut cont de faptul că această metodă poate arunca excepții de tipul InterruptedException.
public class Main {
public static void main(String[] args) {
MyThread t = new MyThread();
t.start();
try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
Trimiterea de parametri unui thread și obținerea de rezultate de la acesta
Pentru a trimite parametri unui thread, se va folosi constructorul clasei care înglobează logica thread-ului pe care dorim să îl implementăm (indiferent de metoda de implementare a acestuia - prin moștenire sau implementeare de interfață). Pentru a obține un rezultat de la un thread care și-a terminat execuția (apelul metodei join() a întors) putem folosi fie metode de tip getter care vor întoarce rezultatul, fie putem accesa în mod direct câmpul rezultat în cazul în care acest este definit ca public.
public class Task extends Thread {
private int id;
private int result;
public Task(int id) {
this.id = id;
}
public void run() {
result = id * id;
}
public int getResult() {
return result;
}
}
public class Main {
public static void main(String[] args) {
int NUMBER_OF_THREADS = 4;
Thread[] t = new Thread[NUMBER_OF_THREADS];
for (int i = 0; i < NUMBER_OF_THREADS; ++i) {
t[i] = new Task(i);
t[i].start();
}
for (int i = 0; i < NUMBER_OF_THREADS; ++i) {
try {
t[i].join();
System.out.println("Thread " + i + " computed result " + ((Task)t[i]).getResult() + ".");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}