web-dev-qa-db-fra.com

Attendez que la valeur booléenne change d'état

J'ai un thread qui attend une valeur booléenne pour changer comme ceci:

while(!value)
{
  Thread.sleep(1000)
}
// Do some work after change of the value

Ce n'est pas ma façon préférée de le faire, à cause de la consommation massive de CPU.

Existe-t-il un moyen de bloquer le thread jusqu'à ce que la valeur booléenne le modifie?

40
Marcel Höll

Ce n'est pas ma façon préférée de le faire, à cause de la consommation massive de CPU.

Si c'est votre code de travail, conservez-le ainsi. Vérifier une valeur booléenne une fois par seconde ne provoque AUCUNE charge mesurable du processeur. Pas du tout.

Le vrai problème est que le thread qui vérifie la valeur peut ne pas voir un changement qui s'est produit pendant une période arbitrairement longue en raison de la mise en cache. Pour vous assurer que la valeur est toujours synchronisée entre les threads, vous devez placer le mot clé volatile dans la définition de variable, c.-à-d.

private volatile boolean value;

Notez que placer l'accès dans un bloc synchronized, par exemple lorsque vous utilisez la solution basée sur la notification décrite dans d'autres réponses, aura le même effet.

72
Michael Borgwardt

Vous avez besoin d'un mécanisme qui évite les temps d'attente. L'ancien wait/notify Le mécanisme est semé d'embûches, préférez donc quelque chose de la Java.util.concurrent _ bibliothèque, par exemple CountDownLatch :

public final CountDownLatch latch = new CountDownLatch(1);

public void run () {
  latch.await();
  ...
}

Et à l'autre appel

yourRunnableObj.latch.countDown();

Cependant, démarrer un thread pour ne rien faire d'autre qu'attendre que cela soit nécessaire n'est toujours pas la meilleure solution. Vous pouvez également employer un ExecutorService auquel vous soumettez comme tâche le travail qui doit être effectué lorsque la condition est remplie.

45
Marko Topolnik

Que diriez-vous wait-notify

private Boolean bool = true;
private final Object lock = new Object();

private Boolean getChange(){
  synchronized(lock){
    while (bool) {
      bool.wait();
    }
   }
  return bool;
}
public void setChange(){
   synchronized(lock){
       bool = false;
       bool.notify();
   }
}
7

Ok peut-être que celui-ci devrait résoudre votre problème. Notez que chaque fois que vous effectuez une modification, vous appelez la méthode change () qui libère l’attente.

Integer any = new Integer(0);

public synchronized boolean waitTillChange() {
    any.wait();
    return true;
}

public synchronized void change() {
    any.notify();
}
2
luiso1979

Je préfère utiliser le mécanisme mutex dans de tels cas, mais si vous voulez vraiment utiliser booléen, vous devez le déclarer volatil (pour fournir la visibilité du changement sur les threads) et exécuter simplement le cycle sans corps avec ce booléen comme condition:

//.....some class

volatile boolean someBoolean; 

Thread someThread = new Thread() {

    @Override 
    public void run() {
        //some actions
        while (!someBoolean); //wait for condition 
        //some actions 
    }

};
1
oleg.lukyrych