Ответ 1
Semaphore
похоже, что он может быть ближе к тому, что вы ищете, на самом деле - он позволяет подождать, пока один или несколько "Разрешения" доступны. AtomicInteger
не предназначен для использования, как вы его используете.
Есть ли способ подождать AtomicInteger
, чтобы мне не пришлось спать мой текущий поток и продолжать проверять AtomicInteger
, как этот
while(atomicInt.get() >= 0) {
Thread.sleep(1000)
}
Я знаю, что есть такая вещь, как CountDownLatch
, но это только позволяет мне уменьшаться. Мне также нужно, чтобы он мог увеличивать
Далее BackStory -
У меня есть цикл, создающий потоки, и мне нужно дождаться завершения одного из потоков, прежде чем создавать новый поток. Тем не менее, я использую Executors.newFixedThreadPool(numThreads)
, и единственный способ подождать, похоже, заключается в том, чтобы вызвать метод shutdown wait end, а затем создать новый threadPool, поэтому вместо этого я использовал атомное целое, чтобы отслеживать, сколько потоков было запущено, и/или в очереди, чтобы при уменьшении этого числа я мог продолжить цикл.
Semaphore
похоже, что он может быть ближе к тому, что вы ищете, на самом деле - он позволяет подождать, пока один или несколько "Разрешения" доступны. AtomicInteger
не предназначен для использования, как вы его используете.
Я думаю, что вы действительно хотите обработать какое-то событие. Это событие может, в свою очередь, увеличивать целое число. Взгляните на BlockingQueue.
Очередь, которая дополнительно поддерживает операции, которые ждут, когда очередь становится непустой при извлечении элемента, и подождите, пока пространство станет доступным в очереди при хранении элемента.
Код может выглядеть примерно так:
MyEvent incrementEvent = queue.take(); //blocks until an event is added to the queue
// increment int and do logic here
Я думаю, что более близкое совпадение с тем, что вам нужно, это Phaser. Мое грубое понимание заключается в том, что оно немного похоже на счетчик приращений, где вы можете блокировать до тех пор, пока номер не будет увеличен.
// This constructor one party (so it expects one advance per phase).
Phaser phaser = new Phaser(1);
try {
// This will timeout as phase 0 hasn't arrived yet.
phaser.awaitAdvanceInterruptibly(0, 1, TimeUnit.MILLISECONDS);
fail();
}
catch (TimeoutException expected) {
}
// Arrive phase 0
phaser.arrive();
phaser.awaitAdvance(0);
try {
// Phase 1 will timeout..
phaser.awaitAdvanceInterruptibly(1, 1, TimeUnit.MILLISECONDS);
fail();
}
catch (TimeoutException expected) {
}
// Arrive phase 1
phaser.arrive();
phaser.awaitAdvance(0);
phaser.awaitAdvance(1);
Если вы используете API-интерфейс Executors, правильный способ дождаться завершения задачи - использовать API будущего. Пример кода показан ниже:
Future<?> future = threadPool.submit(task);
future.get();
Простое решение с CompletableFuture
Создать CompletableFuture, доступный для обоих потоков thread1, thread2
private CompletableFuture<Integer> future = new CompletableFuture<>();
Ожидание значения в потоке 1 (или в нескольких потоках)
Integer value = future.join();
Рассчитать стоимость в thread2 и завершить будущее
if (!future.isDone()) future.complete(calculatedValue);