1

正如标题所述,我对基于线程的结构有疑问。我需要做的是:

  • 一个线程在循环中运行并检查列表中是否存在某些内容,如果存在则对对象执行一些操作,然后将其从列表中删除

  • 从“外部”调用并将新对象添加到此列表的函数。

这是我的方法:

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);
            }
            }
        }
    }
}

这是正确的方法吗?我是否也应该同步添加到此列表中?

4

4 回答 4

9

看起来您应该尝试java.util.concurrent.BlockingQueue的实现,而不是尝试自己编写!我怀疑LinkedBlockingQueue会很好地为您工作。您可以从多个源将条目写入队列,并且您的使用者线程将以线程安全的方式将每个条目取出并依次处理它。

请注意,您的消费者线程BlockingQueue等待(通过调用该take()方法)。但是,您上面的实现将在等待队列中处理条目的同时旋转并消耗 CPU(如果您运行它并监视 CPU 使用情况,这应该很明显)。

这是一篇解释性文章

于 2012-10-02T13:20:25.630 回答
1

您需要同步对列表的所有访问:

public void addToList(X toAdd){
    synchronized(listOfObject) {
        listOfObject.add(toAdd);
    }
}

或者,您可以使用 List 的线程安全实现,例如CopyOnWriteArrayList,在这种情况下,您可以删除所有synchronized块。

ps:正如另一个答案中提到的,您似乎正在重新实现ArrayBlockingQueue

于 2012-10-02T13:21:03.513 回答
1

最好使用Collections.synchronizedList()包装器而不是手动同步块。

于 2012-10-02T13:22:22.600 回答
1

您似乎正在尝试为线程创建队列以处理添加的元素。

更简单的方法是使用 ExecutorService。

ExecutorService service = Executors.newSingleThreadedPool();

// to add a task.
service.submit(new Runnable() {
    public void run() {
       // process X here
    }
});
于 2012-10-02T13:22:26.423 回答