Nein, die Methoden müssen nicht synchronisiert werden, und Sie müssen keine Methoden definieren. Sie befinden sich bereits in ConcurrentLinkedQueue. Verwenden Sie sie einfach. ConcurrentLinkedQueue führt alle Sperr- und sonstigen Operationen aus, die Sie intern benötigen. Ihre Produzenten fügen Daten in die Warteschlange ein und Ihre Konsumenten fragen danach ab.
Erstellen Sie zunächst Ihre Warteschlange:
Queue<YourObject> queue = new ConcurrentLinkedQueue<YourObject>();
Übergeben Sie nun, wo immer Sie Ihre Produzenten- / Konsumentenobjekte erstellen, die Warteschlange, damit sie irgendwo ihre Objekte ablegen können (Sie könnten stattdessen einen Setter dafür verwenden, aber ich bevorzuge es, solche Dinge in einem Konstruktor zu tun):
YourProducer producer = new YourProducer(queue);
und:
YourConsumer consumer = new YourConsumer(queue);
und füge Sachen in deinem Produzenten hinzu:
queue.offer(myObject);
und nehmen Sie Sachen in Ihrem Verbraucher heraus (wenn die Warteschlange leer ist, gibt poll () null zurück, also überprüfen Sie es):
YourObject myObject = queue.poll();
Weitere Informationen finden Sie im Javadoc
BEARBEITEN:
Wenn Sie das Warten blockieren müssen, bis die Warteschlange nicht leer ist, möchten Sie wahrscheinlich eine LinkedBlockingQueue verwenden und die Methode take () verwenden. LinkedBlockingQueue hat jedoch eine maximale Kapazität (standardmäßig Integer.MAX_VALUE, die über zwei Milliarden beträgt) und kann daher je nach Ihren Umständen angemessen sein oder auch nicht.
Wenn nur ein Thread Inhalte in die Warteschlange stellt und ein anderer Thread Inhalte aus der Warteschlange entfernt, ist ConcurrentLinkedQueue wahrscheinlich übertrieben. Dies ist eher der Fall, wenn Hunderte oder sogar Tausende von Threads gleichzeitig auf die Warteschlange zugreifen. Ihre Bedürfnisse werden wahrscheinlich erfüllt durch:
Queue<YourObject> queue = Collections.synchronizedList(new LinkedList<YourObject>());
Ein Plus davon ist, dass die Instanz (Warteschlange) gesperrt wird, sodass Sie in der Warteschlange synchronisieren können, um die Atomizität zusammengesetzter Operationen sicherzustellen (wie von Jared erläutert). Sie können dies NICHT mit einer ConcurrentLinkedQueue tun, da alle Vorgänge OHNE Sperren der Instanz ausgeführt werden (unter Verwendung der Variablen java.util.concurrent.atomic). Sie müssen dies NICHT tun, wenn Sie blockieren möchten, während die Warteschlange leer ist, da poll () einfach null zurückgibt, während die Warteschlange leer ist, und poll () atomar ist. Überprüfen Sie, ob poll () null zurückgibt. Wenn dies der Fall ist, warten Sie () und versuchen Sie es erneut. Keine Notwendigkeit zu sperren.
Schließlich:
Ehrlich gesagt würde ich nur eine LinkedBlockingQueue verwenden. Es ist immer noch übertrieben für Ihre Anwendung, aber die Chancen stehen gut, dass es gut funktionieren wird. Wenn es nicht performant genug ist (PROFIL!), Können Sie immer etwas anderes ausprobieren, und es bedeutet, dass Sie sich nicht mit synchronisierten Dingen befassen müssen:
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 das gleiche. Put wird wahrscheinlich nicht blockiert, da Sie wahrscheinlich nicht zwei Milliarden Objekte in die Warteschlange stellen.