I want to make one thread that puts values to a queue when it gets empty and wait for this condition while it is not. Here’s the code I’ve tried to use, but it prints
Adding new
Taking Value 1
Taking Value 2
Taking Value 3
Taking Value 4
So it is working only one time. What is the problem?
import java.util.concurrent.BlockingQueue;
import java.util.concurrent.LinkedBlockingQueue;
public class SO {
public String test;
public String[] list = new String[] {test};
public static void main(String[] args) {
new SO();
}
public SO() {
go();
}
BlockingQueue<String> qq = new LinkedBlockingQueue<String>();
class Producer implements Runnable {
public void run() {
try {
while (true) {
synchronized (this) {
while (qq.size() > 0)
wait();
System.out.println("Adding new");
qq.put("Value 1");
qq.put("Value 2");
qq.put("Value 3");
qq.put("Value 4");
}
}
} catch (InterruptedException ex) {}
}
}
class Consumer implements Runnable {
public void run() {
try {
while(true) {
System.out.println("Taking " + qq.take()+". "+String.valueOf(qq.size())+" left");
Thread.sleep(1000);
}
} catch (InterruptedException ex) {}
}
}
public void go() {
Producer p = new Producer();
Consumer c = new Consumer();
new Thread(p).start();
new Thread(c).start();
}
}
The wait() will continue forever because you never call notify().
You could wait on the queue and call notify on that when you want the waiting thread to wakeup. To do this you would change Producer to read:
synchronized (qq) { while (qq.size() > 0) qq.wait(); System.out.println("Adding new"); qq.put("Value 1"); qq.put("Value 2"); qq.put("Value 3"); qq.put("Value 4"); }And change Consumer to read:
while(true) { synchronized (qq) { System.out.println("Taking " + qq.take() + ". " + String.valueOf(qq.size()) + " left"); qq.notify(); } Thread.sleep(1000); }As Steve says in his answer you could also use wait() in the consumer thread so it can wait until there is something in the list rather than sleeping. So your code would become:
import java.util.concurrent.BlockingQueue; import java.util.concurrent.LinkedBlockingQueue; public class SO { public String test; public String[] list = new String[] { test }; public static void main(String[] args) { new SO(); } public SO() { go(); } BlockingQueue qq = new LinkedBlockingQueue(); class Producer implements Runnable { public void run() { try { while (true) { synchronized (qq) { if (!qq.isEmpty()) { qq.wait(); } System.out.println("Adding new"); qq.put("Value 1"); qq.put("Value 2"); qq.put("Value 3"); qq.put("Value 4"); qq.notify(); } } } catch (InterruptedException ex) { } } } class Consumer implements Runnable { public void run() { try { while (true) { synchronized (qq) { System.out.println("Taking " + qq.take() + ". " + String.valueOf(qq.size()) + " left"); if (qq.isEmpty()) { qq.notify(); qq.wait(); } } } } catch (InterruptedException ex) { } } } public void go() { Producer p = new Producer(); Consumer c = new Consumer(); new Thread(p).start(); new Thread(c).start(); } }