Semafor
Semafory są zwykle używane, gdy konieczne jest ograniczenie liczby wątków podczas pracy z systemem plików. Dostęp do pliku lub innego udostępnionego zasobu jest kontrolowany przez licznik. Jeśli jego wartość jest większa od zera, dostęp jest dozwolony, ale jednocześnie licznik się zmniejszy.
W momencie, gdy licznik zwróci zero, bieżący wątek zostanie zablokowany do czasu zwolnienia zasobu przez inny wątek. Liczba parametrów uprawnień musi być ustawiona za pomocą konstruktora.
Musisz wybrać ten parametr indywidualnie, w zależności od mocy komputera lub laptopa.
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 inne
CountDownLatch — umożliwia wielu wątkom oczekiwanie na zakończenie określonej liczby operacji wykonanych na innych wątkach. Przykładem jest instalacja aplikacji: nie rozpocznie się, dopóki nie zaakceptujesz warunków użytkowania, dopóki nie wybierzesz folderu, w którym ma zostać zainstalowany nowy program i tak dalej. Jest do tego specjalna metoda countDown() - ta metoda zmniejsza licznik odliczania o jeden.
Gdy tylko liczba spadnie do zera, wszystkie oczekujące wątki w oczekiwaniu będą kontynuować swoją pracę, a wszystkie kolejne wywołania oczekiwania przejdą bez czekania. Licznik odliczania jest licznikiem jednorazowym i nie można go zresetować.
CyclicBarrier - służy do synchronizacji określonej liczby wątków w jednym punkcie. Bariera zostaje osiągnięta, gdy N wątków wywołuje metodę await(...) i blokuje. Następnie licznik zostaje zresetowany do pierwotnej wartości, a oczekujące wątki zostaną zwolnione. Dodatkowo w razie potrzeby istnieje możliwość uruchomienia niestandardowego kodu przed odblokowaniem wątków i wyzerowaniem licznika. W tym celu obiekt z implementacją interfejsu Runnable jest przekazywany przez konstruktora .
Exchanger<V> — klasa Exchanger jest przeznaczona do wymiany danych pomiędzy wątkami. Jest wpisany i określa typ danych, które wątki muszą wymieniać.
Dane są wymieniane przy użyciu jedynej metody exchange() tej klasy :
V exchange(V x) throws InterruptedException
V exchange(V x, long timeout, TimeUnit unit) throws InterruptedException, TimeoutException
Parametr x reprezentuje bufor danych do wymiany. Druga forma metody definiuje również parametr timeout , timeout i unit , typ jednostki czasu używanej dla parametru timeout .
Klasa Phaser umożliwia synchronizację wątków reprezentujących pojedynczą fazę lub etap w wykonywaniu ogólnej akcji. Phaser definiuje obiekt synchronizacji, który czeka na zakończenie określonej fazy. Następnie Phaser przechodzi do następnego etapu lub fazy i czeka na jej ponowne zakończenie.
Podczas pracy z klasą Phaser często najpierw tworzy się jej obiekt. Następnie musimy zarejestrować wszystkich uczestników. Aby zarejestrować każdego uczestnika, należy wywołać metodę register() lub można zrezygnować z tej metody, przekazując wymaganą liczbę uczestników do konstruktora Phaser .
Następnie każdy uczestnik wykonuje określony zestaw czynności składających się na fazę. A synchronizator Phaser czeka, aż wszyscy uczestnicy zakończą wykonywanie fazy. Aby poinformować synchronizator, że faza się zakończyła, uczestnik musi wywołać metodę arrival() lub arrivalAndAwaitAdvance() . Następnie synchronizator przechodzi do następnej fazy.
GO TO FULL VERSION