MySQL Java JavaScript PHP Python HTML-CSS C-sharp

Crearea și execuția firelor de execuție

Pentru a crea un nou fir de execuție, putem crea o nouă clasă fie moștenind-o de la clasa Thread, fie implementând în clasă interfața Runnable.

Moștenirea de la clasa Thread

Să creăm propria clasă pe baza clasei Thread:

class JThread extends Thread {
     
   JThread(String name){
       super(name);
   }
     
   public void run(){
         
       System.out.printf("%s started... \n", Thread.currentThread().getName());
       try{
           Thread.sleep(500);
       }
       catch(InterruptedException e){
           System.out.println("Thread has been interrupted");
       }
       System.out.printf("%s finished... \n", Thread.currentThread().getName());
   }
}
 
public class Program {
 
   public static void main(String[] args) {
         
       System.out.println("Main thread started...");
       new JThread("JThread").start();
       System.out.println("Main thread finished...");
   }
}

Clasa firului de execuție se numește JThread. Se presupune că în constructorul clasei se transmite numele firului, care apoi este transmis în constructorul clasei de bază. În constructorul propriei clase de fir, putem transmite diverse date, dar principalul este să apelăm constructorul clasei de bază Thread, în care se transmite numele firului.

De asemenea, în JThread se suprascrie metoda run(), al cărei cod va reprezenta codul ce se execută în fir.

În metoda main, pentru a porni firul JThread, se apelează metoda start(), după care începe execuția codului definit în metoda run:

new JThread("JThread").start();

Ieșirea în consolă:

Main thread started...
Main thread finished...
JThread started...
JThread finished...

Aici, în metoda main, în constructorul JThread se transmite un nume arbitrar al firului, iar apoi se apelează metoda start(). Această metodă invocă de fapt metoda suprascrisă run() a clasei JThread.

Observați că firul principal își termină execuția mai devreme decât firul fiu JThread.

Similar cu crearea unui fir, putem porni mai multe fire simultan:

public static void main(String[] args) {
       
   System.out.println("Main thread started...");
   for(int i=1; i < 6; i++)
       new JThread("JThread " + i).start();
   System.out.println("Main thread finished...");
}

Ieșirea în consolă:

Main thread started...
Main thread finished...
JThread 2 started...
JThread 5 started...
JThread 4 started...
JThread 1 started...
JThread 3 started...
JThread 1 finished...
JThread 2 finished...
JThread 5 finished...
JThread 4 finished...
JThread 3 finished...

Așteptarea finalizării firului

În exemplele de mai sus, Main thread se termina înaintea firului fiu. În general, o situație mai comună este când firul principal se termină ultimul. Pentru aceasta, trebuie să aplicăm metoda join(). În acest caz, firul curent va aștepta finalizarea firului pentru care se apelează metoda join:

public static void main(String[] args) {
       
   System.out.println("Main thread started...");
   JThread t = new JThread("JThread ");
   t.start();
   try{
       t.join();
   }
   catch(InterruptedException e){
       System.out.printf("%s has been interrupted", t.getName());
   }
   System.out.println("Main thread finished...");
}

Metoda join() face ca firul care o apelează (în acest caz, Main thread) să aștepte finalizarea firului pentru care se aplică join (în acest caz, JThread).

Ieșirea în consolă:

Main thread started...
JThread started...
JThread finished...
Main thread finished...

Dacă în program sunt utilizate mai multe fire fiu, iar firul principal trebuie să se termine după acestea, pentru fiecare fir fiu trebuie să apelăm metoda join.

Implementarea interfeței Runnable

O altă modalitate de a defini un fir este prin implementarea interfeței Runnable. Această interfață are o singură metodă run:

interface Runnable{
   void run();
}

În metoda run(), se definește de fapt codul care se execută la pornirea firului.

După definirea obiectului Runnable, acesta este transmis unui constructor al clasei Thread:

Thread(Runnable runnable, String threadName)

Pentru implementarea interfeței, să definim următoarea clasă MyThread:

class MyThread implements Runnable {
     
   public void run(){
         
       System.out.printf("%s started... \n", Thread.currentThread().getName());
       try{
           Thread.sleep(500);
       }
       catch(InterruptedException e){
           System.out.println("Thread has been interrupted");
       }
       System.out.printf("%s finished... \n", Thread.currentThread().getName());
   }
}
 
public class Program {
 
   public static void main(String[] args) {
         
       System.out.println("Main thread started...");
       Thread myThread = new Thread(new MyThread(),"MyThread");
       myThread.start();
       System.out.println("Main thread finished...");
   }
}

Implementarea interfeței Runnable este foarte asemănătoare cu suprascrierea clasei Thread. De asemenea, în metoda run se definește codul care suspendă firul pentru 500 de milisecunde.

În metoda main se apelează constructorul Thread, căruia i se transmite obiectul MyThread. Și pentru a porni firul, se apelează metoda start(). În final, consola va afișa ceva de genul:

Main thread started...
Main thread finished...
MyThread started...
MyThread finished...

Deoarece Runnable reprezintă de fapt o interfață funcțională, care definește o singură metodă, obiectul acestei interfețe poate fi reprezentat sub forma unei expresii lambda:

public class Program {
 
   public static void main(String[] args) {
         
       System.out.println("Main thread started...");
       Runnable r = ()->{
           System.out.printf("%s started... \n", Thread.currentThread().getName());
           try{
               Thread.sleep(500);
           }
           catch(InterruptedException e){
               System.out.println("Thread has been interrupted");
           }
           System.out.printf("%s finished... \n", Thread.currentThread().getName());
       };
       Thread myThread = new Thread(r,"MyThread");
       myThread.start();
       System.out.println("Main thread finished...");
   }
}
← Lecția anterioară Lecția următoare →