Non, les méthodes n'ont pas besoin d'être synchronisées et vous n'avez pas besoin de définir de méthodes; ils sont déjà dans ConcurrentLinkedQueue, utilisez-les simplement. ConcurrentLinkedQueue effectue toutes les opérations de verrouillage et autres dont vous avez besoin en interne; vos producteurs ajoutent des données dans la file d'attente et vos consommateurs les interrogent.
Tout d'abord, créez votre file d'attente:
Queue<YourObject> queue = new ConcurrentLinkedQueue<YourObject>();
Maintenant, où que vous créiez vos objets producteurs / consommateurs, passez dans la file d'attente pour qu'ils aient un endroit où placer leurs objets (vous pouvez utiliser un setter pour cela, à la place, mais je préfère faire ce genre de chose dans un constructeur):
YourProducer producer = new YourProducer(queue);
et:
YourConsumer consumer = new YourConsumer(queue);
et ajoutez-y des éléments dans votre producteur:
queue.offer(myObject);
et enlevez des choses dans votre consommateur (si la file d'attente est vide, poll () retournera null, alors vérifiez-le):
YourObject myObject = queue.poll();
Pour plus d'informations, consultez le Javadoc
ÉDITER:
Si vous devez bloquer l'attente pour que la file d'attente ne soit pas vide, vous souhaiterez probablement utiliser LinkedBlockingQueue et utiliser la méthode take (). Cependant, LinkedBlockingQueue a une capacité maximale (par défaut Integer.MAX_VALUE, qui est supérieur à deux milliards) et peut donc ou non être approprié en fonction de votre situation.
Si vous n'avez qu'un seul thread qui met des éléments dans la file d'attente et qu'un autre thread enlève des éléments de la file d'attente, ConcurrentLinkedQueue est probablement excessif. C'est plus lorsque vous pouvez avoir des centaines, voire des milliers de threads accédant à la file d'attente en même temps. Vos besoins seront probablement satisfaits en utilisant:
Queue<YourObject> queue = Collections.synchronizedList(new LinkedList<YourObject>());
Un avantage de ceci est qu'il se verrouille sur l'instance (file d'attente), vous pouvez donc synchroniser sur la file d'attente pour assurer l'atomicité des opérations composites (comme expliqué par Jared). Vous NE POUVEZ PAS faire cela avec un ConcurrentLinkedQueue, car toutes les opérations sont effectuées SANS verrouillage sur l'instance (à l'aide des variables java.util.concurrent.atomic). Vous n'aurez PAS besoin de faire cela si vous voulez bloquer pendant que la file d'attente est vide, car poll () renverra simplement null alors que la file d'attente est vide et poll () est atomique. Vérifiez si poll () renvoie null. Si c'est le cas, attendez (), puis réessayez. Pas besoin de verrouiller.
Finalement:
Honnêtement, j'utiliserais juste un LinkedBlockingQueue. C'est encore exagéré pour votre application, mais il y a de fortes chances que cela fonctionne correctement. Si ce n'est pas assez performant (PROFILE!), Vous pouvez toujours essayer autre chose, et cela signifie que vous n'avez pas à gérer AUCUN truc synchronisé:
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.
Tout le reste est identique. Put ne bloquera probablement pas, car vous ne risquez pas de mettre deux milliards d'objets dans la file d'attente.