Гибкий CountDownLatch?

Вы могли попытаться использовать плагин Firebug для Firefox для просмотра CSS на кнопке.

24
задан Ravindra babu 18 May 2017 в 16:35
поделиться

4 ответа

java.util.concurrent.Phaser похоже, что он подойдет вам. Планируется, что он будет выпущен в Java 7, но наиболее стабильную версию можно найти на сайте группы интересов jsr166 .

Фейзер - это прославленный Cyclic Barrier. Вы можете зарегистрировать N групп, и когда будете готовы, дождитесь их продвижения на определенном этапе.

Быстрый пример того, как это будет работать:

final Phaser phaser = new Phaser();

public Runnable getRunnable(){
    return new Runnable(){
        public void run(){
            ..do stuff...
            phaser.arriveAndDeregister();
        }
    };
}
public void doWork(){
    phaser.register();//register self
    for(int i=0 ; i < N; i++){
        phaser.register(); // register this task prior to execution 
        executor.submit( getRunnable());
    }
    phaser.arriveAndAwaitAdvance();
}
28
ответ дан 29 November 2019 в 00:01
поделиться

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

Я бы добавил метод waitforWorkDone (производитель) для потребителя. Производитель может добавить свои N задач и вызвать метод ожидания. Метод ожидания блокирует входящий поток, если рабочая очередь не пуста и в данный момент никакие задачи не выполняются.

Потоки-потребители notifyAll () на ожидании блокировки, если их задача завершена, очередь пуста и никакая другая задача не выполняется.

0
ответ дан 29 November 2019 в 00:01
поделиться

Вы, конечно, можете использовать CountDownLatch , защищенный AtomicReference , чтобы ваши задачи были упакованы таким образом:

public class MyTask extends Runnable {
    private final Runnable r;
    public MyTask(Runnable r, AtomicReference<CountDownLatch> l) { this.r = r; }

    public void run() {
        r.run();
        while (l.get() == null) Thread.sleep(1000L); //handle Interrupted
        l.get().countDown();
    }
}

Обратите внимание , что задачи выполняют свою работу, а затем вращают до тех пор, пока не будет установлен обратный отсчет (т. е. общее количество задач станет известным). Как только обратный отсчет установлен, они начинают обратный отсчет и выходят. Они отправляются следующим образом:

AtomicReference<CountDownLatch> l = new AtomicReference<CountDownLatch>();
executor.submit(new MyTask(r, l));

После точки создания / отправки вашей работы, , когда вы знаете, сколько задач вы создали :

latch.set(new CountDownLatch(nTasks));
latch.get().await();
2
ответ дан 29 November 2019 в 00:01
поделиться

Я использовал ExecutorCompletionService для чего-то вроде этого:

ExecutorCompletionService executor = ...;
int count = 0;
while (...) {
    executor.submit(new Processor());
    count++;
}

//Now, pull the futures out of the queue:
for (int i = 0; i < count; i++) {
    executor.take().get();
}

Это включает в себя хранение очереди отправленных задач, поэтому, если ваш список произвольно длинный, ваш метод может быть лучше.

Но не забудьте использовать AtomicInteger для координации, чтобы вы могли увеличивать его в одном потоке и уменьшать в рабочих потоках.

1
ответ дан 29 November 2019 в 00:01
поделиться