Package concurrent

Présentation du package java.util.concurrent

Ce site ne sera plus alimenté de contenu après août 2014. Tous les nouveaux articles seront redigés pour www.waitingforcode.com

Dans cet article on présentera un exemple d'utilisation d'une classe issue du package java.util.concurrent.

Package concurrent en Java

Java a introduit un package qui permet de mieux gérer tous les aspects de programmation concurrentielle. Grâce au java.util.concurrent on peut bloquer les objets, de les notifier qu'une action importante a été correctement exécutée ou même de créer des groupes des Threads. Regardons le code ci-dessus qui introduit les concepts évoqués sur l'exemple d'une queue chez un médecin :

public class MultiMonitors { 
    public static void main(String[] args) {
        Queue queueInst = new Queue();
        new Patient(queueInst, "F1").start();
        new Patient(queueInst, "F2").start();
        new Patient(queueInst, "F3").start();
    }
}

class Queue {
    public boolean isSomebody = false;

    public synchronized void canEntry(String p) {
        System.out.println("Patient " + p + " is checking if he can enter.");
        while (isSomebody) {
            try {
                System.out.println("Patient " + p + " can't enter. He is waiting his turn.");
                wait();
            } catch (Exception e) { }
        }
        isSomebody = true;
        System.out.println("Patient " + p + " has entered.");
    }

    public synchronized void quit(String name) {
        System.out.println("\nPatient " + name + " is going to home.\n");
        isSomebody = false;
        notify();
    }
}

class Patient extends Thread {
    Queue queue = null;
    String name = "";

    public Patient(Queue q, String n) {
        queue = q;
        name = n;
    }
  
    public void run() {
        System.out.println("Run Patient " + name);
        queue.canEntry(name);
        queue.quit(name);
    }
}

On remarque la présence de 2 nouvelles méthodes : wait() et notify(). Leur rôle est crucial dans la synchronisation de la queue. Regardons le résultat pour mieux le comprendre :

Run Patient F1
Run Patient F2
Patient F1 is checking if he can enter.
Patient F1 has entered.
Patient F2 is checking if he can enter.
Patient F2 can't enter. He is waiting his turn.

Patient F1 is going to home.

Patient F2 has entered.

Patient F2 is going to home.

Run Patient F3
Patient F3 is checking if he can enter.
Patient F3 has entered.

Patient F3 is going to home.

Au tout début deux Threads (1 et 2 : T1 et T2) sont lancés. T1 a accédé le premier à la queue. Tout de suite après lui, le T2 a tenté la même chose. Cependant il y avait déjà quelqu'un dans le cabinet du médecin. Le T2 a dû alors attendre (wait()). Une fois la consultation du T1 terminée, une notification est envoyée (notify()) au T2 pour lui signaler qu'il peut entrer. La même opération s'est produite avec le dernier Threadd (T3), qui a été exécuté à la suite des deux précédentes.

Cette technique s'appele guarded blocks. Elle repose sur un attribut partagé par plusieurs Threads. Le fait d'exécuter une action par un Thread est contrôlé par la valeur de cet attribut. Grosso-modo on peut dire que cette instruction correspond à une boucle while. Cependant, elle est moins gourmande en ressource que la boucle qui tourne tout le temps. Ici, grâce à la méthode wait() on indique au Thread d'attendre l'envoi de notification (notify() ou notifyAll()). Ce n'est qu'après qu'il se réveille et continue le traitement.

On a donc deux méthodes pour réveiller un Thread. Leur logique est légèrement différente :
- notify() : réveille le premier Thread endormi
- notifyAll() : réveille tous les Threads. Celui dont la priorité est la plus élévée est alors exécutée

Sans l'appel de l'une de ces méthodes, dans notre queue un patient pourrait ne jamais entrer dans le cabinet du médecin. On peut le constater ci-dessous (appel de la méthode notify() a été supprimé du code) :

Run Patient F2
Run Patient F1
Patient F2 is checking
Patient F1 is checking
Wait
Patient F2 is going to home
Run Patient F3
Patient F3 is checking
Patient F3 is going to home
Bartosz KONIECZNY Concurrence

Une question ? Une remarque ?

*

*

Moi

Développeur d'applications Internet et journaliste passionné par l'adjectif français. Un aigle polonais orienté vers la progression, volant très haut et écoutant du zouk après les matches du foot français.

Vous appréciez mon travail ?

Pour contribuer au développement de ce site, ou pour remercier pour des articles rédigés, vous pouvez faire un don.

Un conseil Symfony1

Comment afficher le schéma du formulaire ?

Symfony 1.4 gérait déjà les formulaires avec une simplicité. Mais dans les situation de débuggage c'était très utile de voir leurs schémas. Pour ce faire, il suffisait d'utiliser :

print_r( $this->form->getWidgetSchema() );