No, i metodi non devono essere sincronizzati e non è necessario definire alcun metodo; sono già in ConcurrentLinkedQueue, basta usarli. ConcurrentLinkedQueue esegue internamente tutte le operazioni di blocco e altre operazioni necessarie; i tuoi produttori aggiungono i dati alla coda e i tuoi consumatori lo chiedono.
Per prima cosa, crea la tua coda:
Queue<YourObject> queue = new ConcurrentLinkedQueue<YourObject>();
Ora, ovunque tu stia creando i tuoi oggetti produttore / consumatore, passa in coda in modo che abbiano un posto dove mettere i loro oggetti (potresti usare un setter per questo, invece, ma preferisco fare questo genere di cose in un costruttore):
YourProducer producer = new YourProducer(queue);
e:
YourConsumer consumer = new YourConsumer(queue);
e aggiungici qualcosa nel tuo produttore:
queue.offer(myObject);
e prendi le cose nel tuo consumatore (se la coda è vuota, poll () restituirà null, quindi controllalo):
YourObject myObject = queue.poll();
Per maggiori informazioni vedere il Javadoc
MODIFICARE:
Se hai bisogno di bloccare l'attesa che la coda non sia vuota, probabilmente vorrai usare LinkedBlockingQueue e usare il metodo take (). Tuttavia, LinkedBlockingQueue ha una capacità massima (il valore predefinito è Integer.MAX_VALUE, che è superiore a due miliardi) e quindi può o non può essere appropriato a seconda delle circostanze.
Se hai solo un thread che inserisce elementi nella coda e un altro thread che estrae elementi dalla coda, ConcurrentLinkedQueue è probabilmente eccessivo. È più per quando potresti avere centinaia o addirittura migliaia di thread che accedono alla coda contemporaneamente. Le tue esigenze saranno probabilmente soddisfatte utilizzando:
Queue<YourObject> queue = Collections.synchronizedList(new LinkedList<YourObject>());
Un vantaggio di questo è che si blocca sull'istanza (coda), quindi puoi sincronizzarti sulla coda per garantire l'atomicità delle operazioni composite (come spiegato da Jared). NON È POSSIBILE farlo con ConcurrentLinkedQueue, poiché tutte le operazioni vengono eseguite SENZA blocco sull'istanza (utilizzando le variabili java.util.concurrent.atomic). NON sarà necessario farlo se si desidera bloccare mentre la coda è vuota, perché poll () restituirà semplicemente null mentre la coda è vuota e poll () è atomico. Controlla se poll () restituisce null. In tal caso, aspetta (), quindi riprova. Non c'è bisogno di bloccare.
Finalmente:
Onestamente, userei solo una LinkedBlockingQueue. È ancora eccessivo per la tua applicazione, ma è probabile che funzioni bene. Se non è abbastanza performante (PROFILO!), Puoi sempre provare qualcos'altro, e significa che non devi occuparti di NESSUNA roba sincronizzata:
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.
Tutto il resto è lo stesso. Put probabilmente non bloccherà, perché è improbabile che tu metta due miliardi di oggetti in coda.