Semafor

Semaforele sunt de obicei folosite atunci când este necesar să se limiteze numărul de fire atunci când se lucrează cu sistemul de fișiere. Accesul la un fișier sau la altă resursă partajată este controlat printr-un contor. Dacă valoarea sa este mai mare decât zero, accesul este permis, dar în același timp contorul va scădea.

În momentul în care contorul revine la zero, firul curent va fi blocat până când resursa este eliberată de un alt fir. Parametrul numărul de permisiuni trebuie setat prin intermediul constructorului.

Trebuie să selectați acest parametru individual, în funcție de puterea computerului sau laptopului dvs.

public class Main {

   public static void main(String[] args) {
       Semaphore sem = new Semaphore(1);
       CommonResource res = new CommonResource();
       new Thread(new MyThread(res, sem, "MyThread_1")).start();
       new Thread(new MyThread(res, sem, "MyThread_2")).start();
       new Thread(new MyThread(res, sem, "MyThread_3")).start();
   }
}

class CommonResource {
   int value = 0;
}

class MyThread implements Runnable {
   CommonResource commonResource;
   Semaphore semaphore;
   String name;
   MyThread(CommonResource commonResource, Semaphore sem, String name) {
       this.commonResource = commonResource;
       this.semaphore = sem;
       this.name = name;
   }

   public void run() {

       try {
           System.out.println(name + "waiting permission");
           semaphore.acquire();
           commonResource.value = 1;
           for (int i = 1; i < 7; i++) {
               System.out.println(this.name + ": " + commonResource.value);
               commonResource.value++;
               Thread.sleep(150);
           }
       } catch (InterruptedException e) {
           System.out.println(e.getMessage() + " " + name);
           Thread.currentThread().interrupt();
       }
       System.out.println(name + "releases permission");
       semaphore.release();
   }
}

CountDownLatch și altele

CountDownLatch - Permite mai multor fire de execuție să aștepte până la finalizarea unui anumit număr de operațiuni efectuate pe alte fire. Un exemplu este instalarea unei aplicații: aceasta nu va începe până când nu acceptați termenii de utilizare, până când nu selectați un folder în care să instalați un nou program și așa mai departe. Există o metodă specială countDown() pentru aceasta - această metodă decrește contorul de numărătoare inversă cu unul.

De îndată ce numărătoarea ajunge la zero, toate firele în așteptare din așteptare își vor continua activitatea și toate apelurile ulterioare de așteptare vor trece fără așteptare. Numărătoarea inversă este un contor unic și nu poate fi resetat.

CyclicBarrier - folosit pentru a sincroniza un anumit număr de fire la un moment dat. Bariera este atinsă atunci când N fire de execuție apelează metoda await(...) și blochează. După aceea, contorul este resetat la valoarea sa inițială, iar firele de execuție în așteptare vor fi eliberate. În plus, dacă este necesar, este posibil să rulați cod personalizat înainte de a debloca firele și de a reseta contorul. Pentru a face acest lucru, un obiect cu o implementare a interfeței Runnable este trecut prin constructor .

Exchanger<V> clasa Exchanger este destinată schimbului de date între fire. Este tastat și tipează tipul de date pe care firele de execuție trebuie să le schimbe.

Schimbul de date se face folosind singura metodă exchange() din această clasă :

V exchange(V x) throws InterruptedException
V exchange(V x, long timeout, TimeUnit unit) throws InterruptedException, TimeoutException

Parametrul x reprezintă tamponul de date care trebuie schimbat. A doua formă a metodei definește, de asemenea, parametrul timeout , timeout și unit , tipul de unitate de timp de utilizat pentru parametrul timeout .

Clasa Phaser vă permite să sincronizați fire care reprezintă o singură fază sau etapă în execuția unei acțiuni generale. Phaser definește un obiect de sincronizare care așteaptă până la finalizarea unei anumite faze. Fazerul trece apoi la următoarea etapă sau fază și așteaptă să se termine din nou.

Când lucrați cu clasa Phaser , este obișnuit să creați mai întâi obiectul său. În continuare, trebuie să înregistrăm toți participanții. Pentru a vă înregistra pentru fiecare participant, metoda register() este numită sau puteți face fără această metodă trecând numărul necesar de participanți constructorului Phaser .

Apoi fiecare participant realizează un anumit set de acțiuni care alcătuiesc faza. Și sincronizatorul Phaser așteaptă până când toți participanții au finalizat execuția fazei. Pentru a informa sincronizatorul că faza sa încheiat, participantul trebuie să apeleze metoda arrive() sau arriveAndAwaitAdvance() . Sincronizatorul trece apoi la următoarea fază.