如何使用 ConcurrentLinkedQueue? [英] How to use ConcurrentLinkedQueue?

查看:36
本文介绍了如何使用 ConcurrentLinkedQueue?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

如何在 Java 中使用 ConcurrentLinkedQueue?
使用这个LinkedQueue,我需要担心队列中的并发吗?或者我是否只需要定义两种方法(一种用于从列表中检索元素,另一种用于将元素添加到列表中)?
注意:显然这两种方法必须同步.对吗?

How do I use a ConcurrentLinkedQueue in Java?
Using this LinkedQueue, do I need to be worried about concurrency in the queue? Or do I just have to define two methods (one to retrive elements from the list and another to add elements to the list)?
Note: obviously these two methods have to be synchronized. Right?

我想要做的是:我有一个类(在 Java 中)用一种方法从队列中检索项目,另一个类用一种方法将项目添加到队列.从列表中添加和检索的项目是我自己的类的对象.

What I'm trying to do is this: I have a class (in Java) with one method to retrieve items from the queue and another class with one method to add items to the queue. The items added and retrieved from the list are objects of my own class.

还有一个问题:我需要在remove方法中做这个:

One more question: do I need to do this in the remove method:

while (queue.size() == 0){ 
  wait(); 
  queue.poll();
}

我只有一个消费者和一个生产者.

I only have one consumer and one producer.

推荐答案

不需要,方法不需要同步,也不需要定义任何方法;它们已经在 ConcurrentLinkedQueue 中,只需使用它们.ConcurrentLinkedQueue 在内部完成所有您需要的锁定和其他操作;您的生产者将数据添加到队列中,您的消费者会对其进行轮询.

No, the methods don't need to be synchronized, and you don't need to define any methods; they are already in ConcurrentLinkedQueue, just use them. ConcurrentLinkedQueue does all the locking and other operations you need internally; your producer(s) adds data into the queue, and your consumers poll for it.

首先,创建您的队列:

Queue<YourObject> queue = new ConcurrentLinkedQueue<YourObject>();

现在,无论您在何处创建生产者/消费者对象,都要传入队列,以便它们有地方放置对象(您可以为此使用 setter,但我更喜欢在构造函数中执行此类操作):

Now, wherever you are creating your producer/consumer objects, pass in the queue so they have somewhere to put their objects (you could use a setter for this, instead, but I prefer to do this kind of thing in a constructor):

YourProducer producer = new YourProducer(queue);

和:

YourConsumer consumer = new YourConsumer(queue);

并在您的生产者中添加内容:

and add stuff to it in your producer:

queue.offer(myObject);

并在您的消费者中取出东西(如果队列为空,poll() 将返回 null,因此请检查它):

and take stuff out in your consumer (if the queue is empty, poll() will return null, so check it):

YourObject myObject = queue.poll();

有关详细信息,请参阅 Javadoc

For more info see the Javadoc

如果你需要阻塞等待队列不为空,你可能想使用一个 LinkedBlockingQueue,并使用 take() 方法.但是,LinkedBlockingQueue 具有最大容量(默认为 Integer.MAX_VALUE,超过 20 亿),因此可能适合也可能不适合,具体取决于您的情况.

If you need to block waiting for the queue to not be empty, you probably want to use a LinkedBlockingQueue, and use the take() method. However, LinkedBlockingQueue has a maximum capacity (defaults to Integer.MAX_VALUE, which is over two billion) and thus may or may not be appropriate depending on your circumstances.

如果您只有一个线程将内容放入队列,而另一个线程将内容从队列中取出,则 ConcurrentLinkedQueue 可能有点矫枉过正.当您可能有数百甚至数千个线程同时访问队列时,更是如此.使用以下方法可能会满足您的需求:

If you only have one thread putting stuff into the queue, and another thread taking stuff out of the queue, ConcurrentLinkedQueue is probably overkill. It's more for when you may have hundreds or even thousands of threads accessing the queue at the same time. Your needs will probably be met by using:

Queue<YourObject> queue = Collections.synchronizedList(new LinkedList<YourObject>());

另外一个好处是它锁定了实例(队列),因此您可以在队列上进行同步以确保复合操作的原子性(如 Jared 所解释的).您不能使用 ConcurrentLinkedQueue 执行此操作,因为所有操作都是在不锁定实例的情况下完成的(使用 java.util.concurrent.atomic 变量).如果您想在队列为空时阻塞,则不需要这样做,因为 poll() 将在队列为空时简单地返回 null,而 poll() 是原子的.检查 poll() 是否返回 null.如果是,请等待(),然后再试一次.无需锁定.

A plus of this is that it locks on the instance (queue), so you can synchronize on queue to ensure atomicity of composite operations (as explained by Jared). You CANNOT do this with a ConcurrentLinkedQueue, as all operations are done WITHOUT locking on the instance (using java.util.concurrent.atomic variables). You will NOT need to do this if you want to block while the queue is empty, because poll() will simply return null while the queue is empty, and poll() is atomic. Check to see if poll() returns null. If it does, wait(), then try again. No need to lock.

老实说,我只是使用 LinkedBlockingQueue.它对您的应用程序来说仍然是矫枉过正,但很有可能它会正常工作.如果它的性能不够(配置文件!),你总是可以尝试其他的东西,这意味着你不必处理任何同步的东西:

Honestly, I'd just use a LinkedBlockingQueue. It is still overkill for your application, but odds are it will work fine. If it isn't performant enough (PROFILE!), you can always try something else, and it means you don't have to deal with ANY synchronized stuff:

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.

其他都一样.Put 可能不会阻塞,因为您不太可能将 20 亿个对象放入队列中.

Everything else is the same. Put probably won't block, because you aren't likely to put two billion objects into the queue.

这篇关于如何使用 ConcurrentLinkedQueue?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆