Warten auf Bedingung in Java
Möchte ich einen thread, stellt Werte in eine queue, wenn er leer wird, und warten Sie für diesen Zustand, während man es nicht ist. Hier ist der code, den ich versucht habe zu verwenden, aber es druckt
Adding new
Taking Value 1
Taking Value 2
Taking Value 3
Taking Value 4
Also es funktioniert nur ein mal. Was ist das 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();
}
}
Anstelle der Verwendung von wait/notify-und damit verbundenen Größe die überprüfung der Logik, der Sie dies tun könnte (je nachdem, ob oder nicht, Sie wollen immer mehr als ein Objekt in der Warteschlange für den Verbrauch) mit
LinkedBlockingQueue.put
auf eine Warteschlange von Kapazität 1. Die put
Methode in javadocs sagen: "Fügt das angegebene element am Schwanz der Warteschlange zu warten, wenn notwendig, für Speicherplatz verfügbar."
InformationsquelleAutor Fluffy | 2010-02-28
Du musst angemeldet sein, um einen Kommentar abzugeben.
Wait() wird immer weiter, weil Sie nie aufrufen, notify().
Könnten Sie warten in der Warteschlange und den Anruf benachrichtigt, wenn Sie möchten, dass der wartende thread zu wakeup. Um dies zu tun würden Sie ändern Produzent zu Lesen:
Und ändern Verbraucher zu Lesen:
Als Steve sagt in seiner Antwort, Sie könnte auch mit wait() in der consumer-thread, so kann es warten, bis es etwas in die Liste, anstatt zu schlafen. So würde der code geworden:
InformationsquelleAutor Richard Miskin
wait()
ist nie benachrichtigt.InformationsquelleAutor Stephen Denne
Sice, Sie sind mit
BlockingQueue
Sie nicht verwendensynchronized
, weilBlockingQueue
ist sychronized standardmäßig. Wenn Sie möchten, um die Synchronisierung zu verwenden, als Sie sollten synchronisieren durch das gleiche Objekt:und Verbraucher Methode sollte eingewickelt in
synchronized(theSameObjectInstance)
um Benachrichtigung erhalten, sollten die Verbraucher auch "warten" irgendwo z.B. bei qq ist leer.InformationsquelleAutor Steve
Ihre Anforderungen zu erklären, dass Sie beabsichtigen, Werte in der Warteschlange, wenn es leer ist -- mehrere Werte ich es nehmen, anstatt nur eine. Wenn sich Ihre Anforderungen ändern, etwas zu sagen, dass Sie eine Element in der Warteschlange und warten, bis es konsumiert wird, bevor ein anderer, dann wären Sie reif für den Einsatz
java.util.gleichzeitige.Wärmetauscher
.Sein Verhalten ist ähnlich wie ein
BlockingQueue
der Tiefe, aber es tut noch ein bisschen mehr: Er übergibt ein Objekt in beide Richtungen, wobei jeder Teilnehmer sowohl ein "Produzent" und "konsument". Es ist daher eineExchanger
kann nicht sein, dass ein "producer"'s Angebot ein Element, bis der "Verbraucher" ist auch bereit, einen Artikel zurück. Es ist nicht "fire and forget" für den "producer"; die Produktion und der Verbrauch timing ist verriegelt. Dies verhindert, dass ein tatsächlicher Produzent von überschwemmungen eines Verbrauchers Warteschlange arbeiten-wieder, wieBlockingQueue
-- aber es auch Stände der Erzeuger bis zum Verbraucher abgeschlossen hat, die Letzte Runde der Arbeit.In Ihrem Fall, der Verbraucher kann nicht alles hilfreich, um wieder zurück zum Hersteller. Unabhängig, können Sie ein Protokoll zwischen den Teilnehmern. Wenn der Hersteller will, dass der Verbraucher-thread heruntergefahren wird, kann Sie bieten einen null-Wert. Sobald der Verbraucher akzeptiert den null-Wert, die Hersteller tun könnten, eine weitere Runde der exchange für den Abschluss der shutdown-Anforderung und Einziehung der endgültige Ergebnis der Verbraucher.
InformationsquelleAutor seh