简体   繁体   中英

How to create a thread that waits for a boolean variable to become true?

I have a function that needs to be called once a boolean variable is true. I tried using a while loop in a thread but it doesn't work. Here is what I've tried:

public class MyRunnable implements Runnable {

public void run() {
    while (true) {
         if (conditions == true) { 
             System.out.println("second");
             break;
         }
    }
}

public static void main(String args[]) {
    boolean condition = false;
    (new Thread(new MyRunnable())).start();
    System.out.println("first\n");
    // set conndition to true
    condition = true;

    }

}

The result shoud be:

first
second

Do not busy-wait for such conditions. Use a blocking idiom. For your simple case you would get away with a new CountDownLatch(1) . First, here's your code, but fixed to compile and run the way you expect:

public class MyRunnable implements Runnable {
  volatile boolean condition = false;

  public void run() {
    while (true) {
      if (condition) {
        System.out.println("second");
        break;
      }
    }
  }
  public static void main(String args[]) {
    final MyRunnable r = new MyRunnable();
    new Thread(r).start();
    System.out.println("first\n");
    r.condition = true;
  }
}

For comparison, a program with a CountDownLatch :

public class MyRunnable implements Runnable {
  final CountDownLatch latch = new CountDownLatch(1);

  public void run() {
    try { latch.await(); } catch (InterruptedException e) {}
    System.out.println("second");
  }

  public static void main(String args[]) {
    final MyRunnable r = new MyRunnable();
    new Thread(r).start();
    System.out.println("first\n");
    r.latch.countDown();
  }
}

To truly notice the difference, add a Thread.sleep(20000) after println("first") and hear the difference in the sound of your computer's fan working hard to dissipate the energy the first program is wasting.

This seems like a place for java's wait notify construct.

public class MyRunnable implements Runnable {

  public run() {
    synchronized(this) {
      try {
        wait();
      } catch (InterruptedException e) {
      }
    }
    System.out.println("second");
  }

  public static void main(String args[]) {
    Runnable r = new MyRunnable();    
    Thread t = new Thread(r);
    t.start();
    System.out.println("first\n");
    synchronized (r) {
      r.notify();
    }
  }

}

Don't do it that way. Instead, you can use Object 's built in notify() and wait() methods like so:

public class MyRunnable implements Runnable {

private final Object condition;

public MyRunnable(Object condition) {
    this.condition = condition;
}

public void run() {
    condition.wait();
    System.out.println("second");
}

public void go(String args[]) {
        Object condition = new Object();
        (new Thread(new MyRunnable(condition))).start();
        System.out.println("first\n");
        // set conndition to true
        condition.notify();
    }
}

If you want fancier notification schemes, you can also look in java.util.concurrent for more powerful ways of letting threads wait on more interesting conditions. All of these will be much more CPU-efficient than just spinning until a condition is true, and they're less likely to introduce concurrency bugs due to subtleties in Java's memory model.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM