作为标题状态我有基于线程的结构的问题。我需要做的是:
一个线程在循环中运行并检查列表中是否存在某些内容,如果是,则对对象执行某些操作,然后将其从列表中删除
从“外部”调用的函数,并将新对象添加到此列表中。
这是我的方法:
public class Queue implements Runnable {
private List<X> listOfObjects = new ArrayList<X>;
public void addToList(X toAdd){
listOfObject.add(toAdd);
}
public void run() {
while(true){
synchronized(listOfObjects){
if(!listOfObjects.isEmpty()){
listOfObjects.get(0).doSth();
listOfObjects.remove(0);
}
}
}
}
}
这是正确的方法吗?我是否还要同步添加到此列表?
答案 0 :(得分:9)
看起来你应该尝试java.util.concurrent.BlockingQueue的实现,而不是尝试自己编写!我怀疑LinkedBlockingQueue会很适合你。您可以从多个源写入队列中的条目,并且您的使用者线程将关闭每个条目并以线程安全的方式依次处理它。
请注意,BlockingQueue
的使用者帖子将等待(通过调用take()
方法)。但是,上面的实现将在等待队列中的条目处理时旋转并消耗CPU(如果运行它并监视CPU使用情况,这应该很明显。)
答案 1 :(得分:1)
您需要同步对列表的所有访问:
public void addToList(X toAdd){
synchronized(listOfObject) {
listOfObject.add(toAdd);
}
}
或者,您可以使用List的线程安全实现,例如CopyOnWriteArrayList,在这种情况下,您可以删除所有synchronized
块。
ps:如另一个答案中所述,您认为重新实现ArrayBlockingQueue。
答案 2 :(得分:1)
最好使用Collections.synchronizedList()
包装器而不是手动同步块。
答案 3 :(得分:1)
您似乎正在尝试为线程创建一个队列来处理添加的元素。
更简单的方法是使用ExecutorService。
ExecutorService service = Executors.newSingleThreadedPool();
// to add a task.
service.submit(new Runnable() {
public void run() {
// process X here
}
});