web-dev-qa-db-fra.com

Partage d'une variable entre plusieurs threads différents

Je veux partager une variable entre plusieurs threads comme ceci:

boolean flag = true;
T1 main = new T1();
T2 help = new T2();
main.start();
help.start();

Je voudrais partager flag entre le fil principal et le fil d'aide où ce sont deux classes Java que j'ai créées. Est-il possible de le faire? Merci!

17
user1031431

Tous les deux T1 et T2 peut faire référence à une classe contenant cette variable.
Vous pouvez alors rendre cette variable volatile, ce qui signifie que
Les modifications apportées à cette variable sont immédiatement visibles dans les deux threads.

Voir cet article pour plus d'informations.

Les variables volatiles partagent les caractéristiques de visibilité des caractéristiques synchronisées mais aucune des caractéristiques d'atomicité. Cela signifie que les threads vont automatiquement voir la valeur la plus récente pour les variables volatiles. Ils peuvent être utilisés pour assurer la sécurité des threads, mais uniquement dans un ensemble de cas très restreint: ceux qui n'imposent pas de contraintes entre plusieurs variables ou entre la valeur actuelle d'une variable et ses valeurs futures.

Et notez les avantages/inconvénients de l'utilisation de volatile par rapport à des moyens plus complexes de partage d'état.

28
Brian Agnew

En plus des autres suggestions - vous pouvez également envelopper l'indicateur dans une classe de contrôle et en faire une dernière instance dans votre classe parent:

public class Test {
  class Control {
    public volatile boolean flag = false;
  }
  final Control control = new Control();

  class T1 implements Runnable {
    @Override
    public void run() {
      while ( !control.flag ) {

      }
    }
  }

  class T2 implements Runnable {
    @Override
    public void run() {
      while ( !control.flag ) {

      }
    }
  }

  private void test() {
    T1 main = new T1();
    T2 help = new T2();

    new Thread(main).start();
    new Thread(help).start();
  }

  public static void main(String[] args) throws InterruptedException {
    try {
      Test test = new Test();
      test.test();
    } catch (Exception e) {
      e.printStackTrace();
    }
  }
}
15
OldCurmudgeon

Pour le rendre visible entre les instances de T1 et T2 vous pourriez faire en sorte que les deux classes contiennent une référence à un objet qui contient la variable.

Si la variable doit être modifiée lors de l'exécution des threads, vous devez envisager la synchronisation. La meilleure approche dépend de vos besoins exacts, mais les principales options sont les suivantes:

  • faire la variable volatile;
  • le transformer en AtomicBoolean ;
  • utiliser une synchronisation complète autour du code qui l'utilise.
5
NPE

L'utilisation de static n'aidera pas votre cas.

L'utilisation de synchronize verrouille une variable lorsqu'elle est utilisée par un autre thread.

Vous devez utiliser le mot clé volatile pour maintenir la variable à jour parmi tous les threads.

L'utilisation de volatile est une autre façon (comme le wrapper atomique synchronisé) de sécuriser le thread de classe. Thread safe signifie qu'une méthode ou une instance de classe peut être utilisée par plusieurs threads en même temps sans aucun problème.

4
Bugs Buggy
  1. Le rendre statique pourrait résoudre ce problème.
  2. Référence au thread principal dans un autre thread et rendant cette variable visible
4
Romczyk

Vous pouvez utiliser les variables de verrouillage "a" et "b" et les synchroniser pour verrouiller la "section critique" dans l'ordre inverse. Par exemple. Notifier "a" puis Verrouiller "b", "IMPRIMER", Notifier "b" puis Verrouiller "a".

Veuillez vous référer au code ci-dessous: -

public class EvenOdd {

static int a = 0;

public static void main(String[] args) {

    EvenOdd eo = new EvenOdd();

    A aobj = eo.new A();
    B bobj = eo.new B();

    aobj.a = Lock.lock1;
    aobj.b = Lock.lock2;

    bobj.a = Lock.lock2;
    bobj.b = Lock.lock1;

    Thread t1 = new Thread(aobj);
    Thread t2 = new Thread(bobj);

    t1.start();
    t2.start();

}

static class Lock {
    final static Object lock1 = new Object();
    final static Object lock2 = new Object();
}

class A implements Runnable {

    Object a;
    Object b;

    public void run() {
        while (EvenOdd.a < 10) {
            try {
                System.out.println(++EvenOdd.a + " A ");
                synchronized (a) {
                    a.notify();
                }
                synchronized (b) {
                    b.wait();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

class B implements Runnable {

    Object a;
    Object b;

    public void run() {
        while (EvenOdd.a < 10) {

            try {
                synchronized (b) {
                    b.wait();
                    System.out.println(++EvenOdd.a + " B ");
                }
                synchronized (a) {
                    a.notify();
                }
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

        }
    }
}

}

SORTIE: - 1 A 2 B 3 A 4 B 5 A 6 B 7 A 8 B 9 A 10 B

0
AkashPushPopStack