Как заблокировать и ждать с помощью AtomicBoolean - PullRequest
15 голосов
/ 21 ноября 2011

Я ищу способ приостановить поток.

Я начал с эффективного использования логического флага (называемого «приостановленным») и оборачивания проверки циклом while (пауза).

В цикле while есть Thread.wait(), чтобы заблокировать выполнение.

Я смотрел на AtomicBoolean , который, кажется, делает трюк отдельно от негоне блокируется.

Существует ли альтернативная или расширенная версия AtomicBoolean, которая имеет метод блока?

, то есть что-то вроде AtomicBoolean.getFalse() из AtomoicBoolean.get(false)?

У них есть очередь блокировки, поэтому значение блокировки.

Текущая настройка:

while (paused.get()) {
        synchronized (paused) {
            try {

                paused.wait();
            } catch (Exception e) {
            }

            paused.notify();
        }
    }

с

public void pause() {
    if (paused.compareAndSet(false, true)) {
        synchronized (paused) {
            paused.notify();
        }
    }

}


public void resume() {
    if (paused.compareAndSet(true, false)) {
        synchronized (paused) {
            paused.notify();
        }
    } 
}

Ответы [ 5 ]

12 голосов
/ 21 ноября 2011
    AtomicBoolean lock = new AtomicBoolean(false);
    if(lock.compareAndSet(false, true)){
        try {
            //do something
        } catch(Exception e){
            //error handling
        } finally {
            lock.set(false);
        }
    }

Во-первых, если вы не используете атомарную операцию (что-то вроде test-and-set), AtomicBoolean так же бесполезен, как и обычный логический тип (если они были изменяемыми).Здесь я использую compareAndSet, чтобы он входил в критическую секцию, только если флаг был выключен.Не забывайте всегда разблокировать в конечном итоге.

Чтобы приостановить поток с помощью флага, не переходите к активному ожиданию (какой-то цикл в теле потока спрашивает: «Я приостановлен?»), Поскольку это неэффективная практика,Я бы использовал схему ожидания-уведомления.Когда у потока больше нет работы, он вызывает wait для некоторого объекта.Затем, чтобы перезапустить, другой поток вызывает notify для того же объекта.

Если вы хотите немедленно приостановить (с точки зрения пропуска выполнения, когда установлен флаг), вы можете разделить код на столькошаги, насколько это возможно, и оберните каждый из них тестом, чтобы наконец дождаться паузы:

public void run(){
    while(true){
        if(!paused){
            //do something
        }

        if(!paused){
            //do something
        }

        if(!paused){
            //do something
        }

        if(!paused){
            //do something
        }

        if(paused){
            //wait on some object
        }
    }       
}   

В зависимости от вашего кода шаги могут быть даже вложенными или включать неделимые единицы выполнения, включающие несколько шагов.

4 голосов
/ 28 марта 2018

Используйте CountDownLatch из 1:

CountDownLatch conditionLatch = new CountDownLatch(1);

В месте, где вы хотите подождать, чтобы какое-то условие стало реальностью:

conditionLatch.await();

В месте, которое вы хотите установитьусловие к истине:

conditionLatch.countDown();
3 голосов
/ 21 ноября 2011

Я не уверен, что понял ваш вопрос, в любом случае вы смотрели на класс java.util.concurrent.Semaphore? Семафор с permissions = 1 должен дать вам желаемое поведение, вы можете подражать вашему

помолчал = истина;

инструкция с

semaphore.tryAcquire ();

или

semaphore.acquire ();

если вы хотите заблокировать абонента. Вы можете освободить тему с помощью

semaphore.release ();

1 голос
/ 21 ноября 2011

Вы можете использовать замок.

В вашей теме.

while(!Thread.interrupted()) {
  lock.lock();
  try {
      // do something.
  } finally {
      lock.unlock();
  }
}

// to pause
lock.lock();

// to unpause
lock.unlock(); // has to be the same thread which locked.

Или вы можете уснуть в зависимости от того, как быстро вам нужна нить, чтобы проснуться.

while(atomicBoolean.get()) Thread.sleep(100); // or yield();
0 голосов
/ 21 ноября 2011

Либо вы ждете определенное время, что можно сделать с помощью Thread.sleep(), либо вам нужно дождаться чего-то, что указывало бы, что вам нужно вызвать wait() для объекта, который вы ждут, чтобы быть готовыми.

Если вам действительно нужно вручную указать поток, чтобы он продолжал работать, создайте цикл while(true), содержащий вызов Thread.sleep() и проверку на логическое значение, которое приводит к break, если он установлен правильно. Хотя я не могу придумать причину сделать это.

...