I have a BlockingQueue which is being populated by a thread with put(). But I am confused on how to do take() for the BlockingQueue. Currently I implemented it this way:
String link;
try {
while(!(link = links.take()).isEmpty()) {
System.out.println(link);
}
} catch(InterruptedException ex) {
ex.printStackTrace();
}
Is that right? How is it possible to loop the queue and assign the string variable if not within the conditional statement?
If I have understood correctly, you have asked for a way to take
outside of the condition? Well, it's not that hard:
while (!links.isEmpty()) {
try {
String link = links.take();
// Do stuff.
} catch (InterruptedException e) {
// Exception handling.
}
}
Your current condition !(link = links.take()).isEmpty()
checks if the return value—a string—is empty (length equals 0), not the queue.
Anyhow, please bear in mind that the code above is not atomic, so there's no guarantee that nothing else happens between links.isEmpty()
and links.take()
.
EDIT: You can handle race conditions during the startup with a flag:
BlockingQueue<Integer> numbers = new ArrayBlockingQueue<>(10);
AtomicBoolean flag = new AtomicBoolean(true);
// Producer.
new Thread(() -> {
for (int i = 0; i < 10; i++) {
try {
numbers.put(i);
} catch (InterruptedException e) { /* NOP */ }
}
flag.set(false);
}).start();
// Consumer.
while (flag.get() || !numbers.isEmpty()) {
try {
System.out.println(numbers.take());
} catch (InterruptedException e) { /* NOP */ }
}
The AtomicBoolean
is not necessary here, but it might become handy if you have multiple producers and/or consumers. It's also part of java.util.concurrent
which you definitely should checkout.