Sémaphore

Les sémaphores sont généralement utilisés lorsqu'il est nécessaire de limiter le nombre de threads lors de l'utilisation du système de fichiers. L'accès à un fichier ou à une autre ressource partagée est contrôlé par un compteur. Si sa valeur est supérieure à zéro, l'accès est autorisé, mais en même temps le compteur diminuera.
Au moment où le compteur retourne à zéro, le thread en cours sera bloqué jusqu'à ce que la ressource soit libérée par un autre thread. Le paramètre nombre de permissions doit être défini via le constructeur.
Vous devez sélectionner ce paramètre individuellement, en fonction de la puissance de votre ordinateur ou de votre ordinateur portable.
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 et autres
CountDownLatch - Permet à plusieurs threads d'attendre qu'un certain nombre d'opérations effectuées sur d'autres threads soient terminées. Un exemple est l'installation d'une application : elle ne démarrera pas tant que vous n'aurez pas accepté les conditions d'utilisation, tant que vous n'aurez pas sélectionné un dossier où installer un nouveau programme, etc. Il existe une méthode spéciale countDown() pour cela - cette méthode décrémente le compteur à rebours de un.
Dès que le décompte atteint zéro, tous les threads en attente dans l'attente poursuivront leur travail et tous les appels ultérieurs de l'attente passeront sans attendre. Le compte à rebours est un compteur unique et ne peut pas être réinitialisé.
CyclicBarrier - utilisé pour synchroniser un nombre donné de threads à un moment donné. La barrière est atteinte lorsque N threads appellent la méthode await(...) et bloquent. Après cela, le compteur est réinitialisé à sa valeur d'origine et les threads en attente seront libérés. De plus, si nécessaire, il est possible d'exécuter un code personnalisé avant de débloquer les threads et de réinitialiser le compteur. Pour ce faire, un objet avec une implémentation de l' interface Runnable est passé via le constructeur .
Exchanger<V> — la classe Exchanger est destinée à l'échange de données entre les threads. Il est typé et type le type de données que les threads doivent échanger.
Les données sont échangées en utilisant la seule méthode exchange() de cette classe :
V exchange(V x) throws InterruptedException
V exchange(V x, long timeout, TimeUnit unit) throws InterruptedException, TimeoutException
Le paramètre x représente le tampon de données à échanger. La deuxième forme de la méthode définit également le paramètre timeout , le timeout et unit , le type d'unité de temps à utiliser pour le paramètre timeout .
La classe Phaser vous permet de synchroniser les threads qui représentent une seule phase ou étape dans l'exécution d'une action globale. Phaser définit un objet de synchronisation qui attend qu'une certaine phase soit terminée. Le Phaser passe ensuite à l'étape ou à la phase suivante et attend qu'elle se termine à nouveau.
Lorsque vous travaillez avec la classe Phaser , il est courant de créer d'abord son objet. Ensuite, nous devons inscrire tous les participants. Pour s'inscrire pour chaque participant, la méthode register() est appelée , ou vous pouvez vous passer de cette méthode en passant le nombre requis de participants au constructeur Phaser .
Ensuite, chaque participant effectue un certain ensemble d'actions qui composent la phase. Et le synchroniseur Phaser attend que tous les participants aient terminé l'exécution de la phase. Pour informer le synchroniseur que la phase est terminée, le participant doit appeler la méthode arrive() ou arriveAndAwaitAdvance() . Le synchroniseur passe alors à la phase suivante.
GO TO FULL VERSION