我正在构建一个Java Running类,它将逐个处理一组项。工作时(run
ning),该集合可能会更新(仅添加项目)。
我如何通过确保该列表将考虑新添加的元素来循环该列表?
更新
根据答案,我实现了我在代码审查中建议的代码。
答案
您应该使用Queue
,即java.util.concurrent.ConcurrentLinkedQueue
、java.util.concurrent.LinkedBlockingQueue
、java.util.concurrent.ArrayBlockingQueue
或适合您需要的其他实现之一。
它们有不同的方法,允许您实现不同的场景。您可以检查javadocs中Queue
方法之间的差异(有些方法抛出异常或返回null;有些方法用于查看元素或在删除后检索元素)。
抛出异常返回特殊值
插入添加(e)报价(e)
删除Remove()poll()
检查元素()peek()
在BlockingQueue
实现的情况下,还有两个选项:阻塞方法和超时方法。可能方法的扩展表在它的javadoc中。
仔细选择所需的实施方式。你想要固定容量吗?是否要阻止从空队列中检索?您希望您的队列是有界的还是无界的。如果仍有疑问,请查找解释不同队列类型之间差异的Stack Overflow答案,用谷歌搜索它们或查看javadocs。
咆哮
根据您的设计,您可能会遇到一个问题,也可能不会遇到这个问题——如何判断队列是空的,因为您已经完成了生成元素的工作。您的生产者(无论是向队列中插入元素的人)是否不够快,无法在消费项目之前将其添加到队列中?或者队列是空的,因为所有任务都已完成?在后一种情况下,如果使用阻塞队列,则可以在没有可用的元素时阻塞元素的检索。在这种情况下,您可以考虑使用";"毒丸";标记元素,这意味着生产者已经完成了生产,或者通过使用中间中介类更好地将生产者与消费者解耦,该中介类保存队列,生产者/消费者仅与中介交互。
使用队列(例如java.util.concurrent.LinkedBlockingQueue)而不是列表。队列是专门为这类场景设计的。
不要使用List。
如果我使用Queue
实例,那么可以调用remove()
,并按FIFO顺序检索元素。如果您使用的是List
实例,则不能做出这样的保证。
以以下代码为例:
ArrayList<Integer> list = new ArrayList<Integer>();
list.add(5);
list.add(4);
list.add(3);
list.add(2);
list.add(1);
list.set(4,5);
list.set(3,4);
list.set(2,3);
list.set(1,2);
list.set(0,1);
System.out.println(list);
另外,另一个区别是抽象。有了Queue
实例,您就不必担心索引,如果您不需要List
所提供的一切,这会让您更容易思考。