Is there a way to wait for the change on an atomic

2019-06-15 08:10发布

问题:

Is there a way to wait on an AtomicInteger so that I don't have to keep sleeping my current thread and keep checking on the AtomicInteger like this

while(atomicInt.get() >= 0) {
    Thread.sleep(1000)
}

I know there is such a thing as a CountDownLatch but that only allows me to decrement I also need it to be able to increment

Further BackStory - I have a loop creating threads and I need to wait on one of the threads execution to finish before creating a new thread. I however am using an Executors.newFixedThreadPool(numThreads) and the only way to wait on it seems to be to call the shutdown method await termination and then create a new threadPool so instead I was using an atomic integer to keep track of how many threads were running and/or on the queue so that when that number decreased I could continue with the loop.

回答1:

Semaphore looks like it might be closer to what you're looking for, actually -- it lets you wait until one or more "permits" is available. AtomicInteger isn't meant to be used how you're using it.



回答2:

I think what you really want is to process some event. That event could in turn increment an integer. Take a peek at the BlockingQueue.

A Queue that additionally supports operations that wait for the queue to become non-empty when retrieving an element, and wait for space to become available in the queue when storing an element.

The code could look something like...

MyEvent incrementEvent = queue.take(); //blocks until an event is added to the queue
// increment int and do logic here


回答3:

If you are using Executors API, the right way to wait for task complete is using the Future API. Sample code is show below:

Future<?> future = threadPool.submit(task);
future.get();


回答4:

I think a closer match to what you want is a Phaser. My rough understanding is that its a bit like an incrementing counter where you can block until the number is incremented.

// 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);