Подождите, пока другой поток что-то сделает - PullRequest
0 голосов
/ 27 ноября 2018

У меня есть две темы, A и B.Я хочу следующее:

  • Я хочу позволить A дождаться, пока B не начнет выполнять f().Как только B начинает выполнение f(), A также может продолжить свою работу.
  • Если B уже выполняет f(), когда A сообщает B о своем состоянии, A можетпродолжайте свою работу.
  • Если, однако, B завершил выполнение f(), A должен ждать, пока B не начнет выполнять f() снова в будущем.

В функциях:

// executed by A only
public void waitForB() throws InterruptedException {
    // keep waiting until B starts f()
}

// executed within aroundF() only
public void f() {
}

// executed by B only
public void aroundF() {
    // 1. mark that we are executing f() and inform A
    f()
    // 2. unmark 
}

Я пытался с Semaphore, Phaser и CyclicBarrier, но у меня есть проблемы с пониманием, что использовать здесь.

Мне удалосьреализовать это с блокировкой вручную (см. ниже), но я хотел бы понять, какой из java.util.concurrent классов использовать здесь.

private final    Object  lock      = new Object();
private          boolean executing = false;

public void waitForB() throws InterruptedException {
    synchronized(lock) {
        while(!executing) {
            lock.wait();
        }
    }
}

public void f() {
}

public void aroundF() {
    try {
        synchronized(lock) {
            executing = true;
            lock.notify();
        }
        f();
    } finally {
        executing = false;
    }
}

1 Ответ

0 голосов
/ 28 ноября 2018

Вы можете достичь той же семантики (и более), используя java.util.concurrent.locks.Lock и связанный java.util.concurrent.locks.Condition, например:

public class MyClass {
  private final Lock lock = new ReentrantLock();
  private final Condition condition = lock.newCondition();
  private boolean executing = false;

  public void waitForB() throws InterruptedException {
    lock.lock();
    try {
      while (!executing) {
        condition.await();
      }
    } finally {
      lock.unlock();
    }
  }

  public void f() {
  }

  public void aroundF() {
    try {
      lock.lock();
      try {
        executing = true;
        condition.signal();
      } finally {
        lock.unlock();
      }
      f();
    } finally {
      executing = false;
    }
  }
}
...