【问题标题】:Why does one iteration of my arraylist work, while the other does not?为什么我的arraylist 的一个迭代可以工作,而另一个不行?
【发布时间】:2014-01-10 22:01:31
【问题描述】:

(TLDR:为什么while循环会无限重复,而for循环总是有效?)


我正在编写一个Android 应用程序,并且有一个需要运行的Runnables 队列,然后从该队列中删除:

List<Runnable> queue = new ArrayList<Runnable>();

我想以最佳的方式做到这一点,并想到了以下算法:

synchronized(queue)
{
    while(queue.size() > 0) 
    {
        queue.remove(0).run();
    }
}

这导致了错误,所以我不得不在循环之前添加这个检查:if (queue.size() &gt; 0)(真的有必要吗?)。然而,现在这似乎陷入了一个无限循环。我不得不把我的循环改成这样,效果很好:

synchronized(queue)
{
    for (int i = 0; i < queue.size(); i++)
    {
        queue.get(i).run();
    }
    queue.clear();
}

我的问题是 - 这些循环之间的低级区别是什么?为什么while循环会失败?

【问题讨论】:

  • 什么是错误/异常?
  • @Massimo 没有错误。该应用程序基本上冻结了。
  • 为什么多次编辑队列的内容会更好?您显示的第二个选项仅编辑队列的内容一次,因此无论如何它应该表现得更好。
  • 您是否在多个线程中操作 ArrayList?它不是线程安全的类,所以如果你是,你会看到奇怪的行为。
  • @NathanielJones clear() 循环遍历 ArrayList 中的项目,使得这个 O(n) 时间复杂度 - 所以基本上它就像两个同时 for-循环。第一个选项只会是一次迭代。

标签: java android loops


【解决方案1】:

其实我不能说while循环sn-p冻结的原因。一个明显的区别是,在第一种情况下,while 循环中的条件取决于主体中发生的情况。我的意思是这条线

queue.remove(0).run()

应该减少队列的大小,如果不这样做,循环将不会结束。 在第二种情况下,循环条件不依赖于循环体中发生的事情。队列在 for 循环主体中没有更改,并且当循环开始时,它预定义了将有多少次迭代。所以我的结论是这一行:

queue.remove(0).run()

把事情搞砸了。 你能试试这个吗:

synchronized(queue)
{
    for (int i = 0; i < queue.size(); i++)
    {
        queue.remove(0).run();
    }
}

看看会发生什么。 此问题的可能原因可能是: - 删除方法可能无法正常工作 - 在循环中启动的线程可能会导致问题。

【讨论】:

  • 好答案。不知何故,代码开始工作 - 但我的可运行代码在黑暗中,我认为这提供了 最佳猜测 哪里出了问题(即 - 可能导致延迟或无限循环的原因) .
【解决方案2】:

我刚刚尝试过这个(虽然不是在 Android 中)并且效果很好:

public class Main
{           
    public void run()
    {       
        final Runnable runMe = new Runnable()
        {
            @Override
            public void run()
            {
                System.out.println("Hi");               
            }           
        };

        List<Runnable> queue = new ArrayList<Runnable>() {
            private static final long   serialVersionUID    = 1L;
            {
                add(runMe); add(runMe); add(runMe); add(runMe);
            }
        };

        synchronized(queue)
        {
            while(queue.size() > 0)
            {
                queue.remove(0).run();
            }
        }
    }   

    public static void main(String[] args)
    {       
        new Main().run();
    }
}
猜你喜欢
  • 1970-01-01
  • 2012-06-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多