不需要同步方法,也不需要定义任何方法;它们已经在ConcurrentLinkedQueue中了,只需使用即可。 ConcurrentLinkedQueue会在内部执行所有锁定和其他操作;您的生产者将数据添加到队列中,您的消费者则会轮询它。
首先,创建您的队列:
Queue<YourObject> queue = new ConcurrentLinkedQueue<YourObject>()
现在,无论您在哪里创建生产者/消费者对象,请传递队列,以便它们有地方放置其对象(您也可以使用setter进行此操作,但我更喜欢在构造函数中执行此类操作):
YourProducer producer = new YourProducer(queue);
并且:
YourConsumer consumer = new YourConsumer(queue)
并在生产者中添加内容:
queue.offer(myObject);
从您的消费者中取出内容(如果队列为空,则poll()将返回null,请检查它):
YourObject myObject = queue.poll()
如需更多信息,请参见Javadoc
编辑:
如果您需要阻塞等待队列不为空,您可能需要使用LinkedBlockingQueue并使用take()方法。但是,LinkedBlockingQueue具有最大容量(默认为Integer.MAX_VALUE,超过20亿),因此根据您的情况可能或可能不适用。
如果您只有一个线程将东西放入队列,另一个线程从队列中取出东西,那么ConcurrentLinkedQueue可能过于复杂了。它更适用于可能有数百甚至数千个线程同时访问队列的情况。您的需求可能通过使用以下内容来满足:
Queue<YourObject> queue = Collections.synchronizedList(new LinkedList<YourObject>())
这样做的一个优点是它锁定了实例(队列),因此您可以在队列上同步以确保组合操作的原子性(如Jared所解释的)。使用ConcurrentLinkedQueue时,您无法这样做,因为所有操作都是在不锁定实例的情况下完成的(使用java.util.concurrent.atomic变量)。如果您想在队列为空时阻塞,您将不需要执行此操作,因为poll()在队列为空时只会返回null,并且poll()是原子的。检查是否返回null。如果是,则等待(),然后再试一次。不需要锁定。
最后:
老实说,我只会使用LinkedBlockingQueue。虽然对于您的应用程序来说还过剩,但很可能会正常工作。如果它的性能不够好(进行性能分析!),您可以尝试其他东西,这意味着您不必处理任何同步问题:
BlockingQueue<YourObject> queue = new LinkedBlockingQueue<YourObject>()
queue.put(myObject)
YourObject myObject = queue.take()
其他的都一样。放心使用,可能不会阻塞,因为你不太可能将20亿个对象放入队列中。