Nein, die Methoden müssen nicht synchronisiert werden, und Sie brauchen keine Methoden zu definieren; sie sind bereits in ConcurrentLinkedQueue enthalten, verwenden Sie sie einfach. ConcurrentLinkedQueue führt alle Sperren und andere Operationen, die Sie benötigen, intern aus; Ihr Producer (s) fügt Daten in die Warteschlange ein, und Ihre Konsumenten pollen für sie.
Erstellen Sie zunächst Ihre Warteschlange:
Queue<YourObject> queue = new ConcurrentLinkedQueue<YourObject>();
Nun, wo auch immer Sie Ihre Producer/Consumer-Objekte erstellen, übergeben Sie die Warteschlange, damit sie ihre Objekte irgendwo ablegen können (Sie könnten stattdessen einen Setter dafür verwenden, aber ich ziehe es vor, diese Art von Dingen in einem Konstruktor zu tun):
YourProducer producer = new YourProducer(queue);
und:
YourConsumer consumer = new YourConsumer(queue);
und fügen Sie in Ihrem Produzenten etwas hinzu:
queue.offer(myObject);
und nehmen Sie Dinge in Ihrem Consumer heraus (wenn die Warteschlange leer ist, gibt poll() null zurück, also überprüfen Sie es):
YourObject myObject = queue.poll();
Für weitere Informationen siehe die Javadoc
EDITAR:
Wenn Sie das Warten darauf, dass die Warteschlange nicht leer ist, blockieren müssen, sollten Sie wahrscheinlich eine LinkedBlockingQueue und verwenden Sie die Methode take(). LinkedBlockingQueue hat jedoch eine maximale Kapazität (Standardwert ist Integer.MAX_VALUE, was mehr als zwei Milliarden ist) und kann daher je nach den Umständen geeignet sein oder nicht.
Wenn Sie nur einen Thread haben, der etwas in die Warteschlange stellt, und einen anderen Thread, der etwas aus der Warteschlange nimmt, ist ConcurrentLinkedQueue wahrscheinlich übertrieben. Sie ist eher für den Fall gedacht, dass Hunderte oder gar Tausende von Threads gleichzeitig auf die Warteschlange zugreifen. Ihre Bedürfnisse werden wahrscheinlich durch die Verwendung erfüllt werden:
Queue<YourObject> queue = Collections.synchronizedList(new LinkedList<YourObject>());
Ein Vorteil davon ist, dass es auf die Instanz (Warteschlange) sperrt, so dass Sie auf die Warteschlange synchronisieren können, um die Atomizität von zusammengesetzten Operationen zu gewährleisten (wie von Jared erklärt). Mit einer ConcurrentLinkedQueue können Sie dies NICHT tun, da alle Operationen OHNE Sperren auf der Instanz durchgeführt werden (unter Verwendung von java.util.concurrent.atomic-Variablen). Sie müssen dies NICHT tun, wenn Sie blockieren wollen, während die Warteschlange leer ist, da poll() einfach null zurückgibt, wenn die Warteschlange leer ist, und poll() ist atomar. Prüfen Sie, ob poll() null zurückgibt. Wenn ja, warten Sie() und versuchen Sie es dann erneut. Sperren ist nicht nötig.
Endlich:
Ehrlich gesagt, würde ich einfach eine LinkedBlockingQueue verwenden. Es ist immer noch Overkill für Ihre Anwendung, aber die Chancen sind es wird gut funktionieren. Wenn es nicht performant genug ist (PROFIL!), können Sie immer versuchen, etwas anderes, und es bedeutet, dass Sie nicht haben, um mit jeder synchronisierten Sachen zu beschäftigen:
BlockingQueue<YourObject> queue = new LinkedBlockingQueue<YourObject>();
queue.put(myObject); // Blocks until queue isn't full.
YourObject myObject = queue.take(); // Blocks until queue isn't empty.
Alles andere ist gleich geblieben. Setzen Sie wahrscheinlich wird nicht blockiert, weil Sie wahrscheinlich nicht zwei Milliarden Objekte in die Warteschlange stellen werden.
0 Stimmen
Danke für die Antwort auf meine Frage. Was ich zu tun versuche, ist folgendes: Ich habe eine Klasse (in Java) mit einer Methode zum Abrufen von Elementen aus der Warteschlange und eine andere Klasse mit einer Methode zum Hinzufügen von Elementen zur Warteschlange. Die hinzugefügten und aus der Liste abgerufenen Elemente sind Objekte meiner eigenen Klasse.
2 Stimmen
Sie sollten Ihre Frage bearbeiten und diese Klarstellung in die Frage selbst aufnehmen.