web-dev-qa-db-fra.com

Quelle est la meilleure façon de transmettre des informations entre les threads?

Je veux écouter un serveur pendant que mon programme fait autre chose, lorsqu'un message est reçu du serveur, je veux l'interpréter.

Je connais le filetage, mais je ne sais pas complètement comment cela fonctionne. Si j'ai un thread qui écoute le serveur, comment puis-je transmettre ces données au thread principal pour l'interprétation? Quelle est la meilleure façon pour le thread principal d'envoyer des données au serveur? À quoi sert le modificateur synchronisé?

25
Bakies

Si j'ai un thread qui écoute le serveur, comment puis-je transmettre ces données au thread principal pour l'interprétation? Quelle est la meilleure façon pour le thread principal d'envoyer des données au serveur?

J'utiliserais un BlockingQueue pour cela. Vous définissez un seul BlockingQueue tel que LinkedBlockingQueue . Votre classe d'écoute appelle ensuite queue.take() qui attend que votre serveur appelle queue.put(). Il laisse toute la synchronisation, attend, notifie, etc. à la classe Java au lieu de votre propre code.

À quoi sert le modificateur synchronisé?

Je ferais quelques lectures pour en savoir plus à ce sujet. Ce n'est pas le genre de chose à laquelle on peut répondre dans une réponse courte SO. Le tutoriel de concurrence Java est un bon point de départ.

33
Gray

Si vous souhaitez une communication synchrone entre un thread principal et un thread de traitement, vous pouvez utiliser un SynchronousQueue .

L'idée est que le thread principal transmet des données au thread de traitement en appelant put(), et le thread de traitement appelle take(). Les deux bloquent les opérations.

Notez que si vous souhaitez renvoyer un résultat, les choses peuvent devenir un peu plus complexes car le thread principal doit savoir quand le résultat est prêt. Un CountDownLatch est une bonne primitive pour cela. Vous pouvez faire quelque chose comme ça.

Définissons d'abord une infrastructure de données pour transmettre les données:

public class MethodCall {

    public final String methodName;

    public final Object[] args;

    public final CountDownLatch resultReady;

    public Object result;

    public MethodCall(String methodName, Object[] args) {
        this.methodName = methodName;
        this.args = args;
        this.resultReady = new CountDownLatch(1);
    }

    public void setResult(Object result) {
        this.result = result;
        resultReady.countDown();
    }

    public Object getResult() throws InterruptedException {
        resultReady.await();
        return result;
    }
}

Définissez la file d'attente pour transmettre les données, visibles par les deux threads:

public SynchronousQueue<MethodCall> methodCalls = new SynchronousQueue<MethodCall>();

Pour passer un appel du thread principal au thread de traitement et attendre le résultat:

MethodCall call = new MethodCall(methodName, args);
methodCalls.put(call);
Object result = call.getResult();

Dans le thread de traitement, par exemple dans une méthode run(), vous pouvez alors faire:

for (;;) {
    MethodCall call = methodCalls.take();
    Object res = processStuff(call.methodName, call.args);
    call.setResult(res);
}

processStuff implémente votre logique. Bien sûr, vous devez également gérer les exceptions, gérer les cas de sortie, modifier MethodCall pour avoir des choses plus spécifiques que methodName et args et un Object return , etc.

8
Florent Guillaume

Parcourez quelques didacticiels pour comprendre Java Threads.

http://www.journaldev.com/1079/Java-thread-tutorial

Votre problème semble être comme le modèle producteur-consommateur, vous pouvez utiliser BlockingQueue pour réaliser facilement cette tâche.

Java Blocking Queue

6
Pankaj