简体   繁体   English

为什么我的arraylist的一次迭代工作,而另一次没有?

[英]Why does one iteration of my arraylist work, while the other does not?

( TLDR: Why does the while-loop repeat infinitely, where the for-loop always works? ) TLDR:为什么while循环无限重复,for-loop总是有效?


I am writing an Android app, and have a queue of Runnable s that need to be run, then removed from this queue: 我正在编写一个Android应用程序,并且有一个需要运行的Runnable队列,然后从这个队列中删除:

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

I wanted to do this the most optimal way, and thought of the following algorithm: 我想以最佳方式做到这一点,并考虑以下算法:

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

This caused errors, so I had to add this check: if (queue.size() > 0) before the loop (is that really necessary?). 这导致了错误,所以我不得不在循环之前添加这个检查: if (queue.size() > 0) (真的有必要吗?)。 Now, however, this seems to be stuck in an infinite loop. 然而,现在,这似乎陷入无限循环。 I had to change my loop to this, which works well: 我不得不改变我的循环,这很好用:

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

My question is - what is the low-level difference between these loops? 我的问题是 - 这些循环之间的低级差异是什么? Why does the while loop fail? 为什么while循环失败?

Actually I can not mention the reason why the while loop snippet freezes. 实际上我不能提到while循环片段冻结的原因。 A noticeable difference is that in the first scenario the condition in the while loop depends on what happens in the body. 一个明显的区别是,在第一种情况下,while循环中的条件取决于正文中发生的情况。 What i mean is this line 我的意思是这条线

queue.remove(0).run()

is supposed to decrease the size of the queue and if it does not the loop won't end. 应该减少队列的大小,如果没有,循环将不会结束。 In the second scenario the loop condition does not depend on what happens in the loop body. 在第二种情况下,循环条件不依赖于循环体中发生的情况。 The queue is not changed in the for loop body and when the loop starts it is predefined how many iterations there will be. 队列在for循环体中没有改变,当循环开始时,它预定义了将有多少次迭代。 So my conclusion is that something with this line: 所以我的结论就是这条线:

queue.remove(0).run()

messes the things up. 搞砸了事情。 Can you please try this: 你能试试这个:

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

and see what happens. 看看会发生什么。 The possible reasons for this problem may be: - The remove method may not work properly - Threads started within the loop may cause the problem. 此问题的可能原因可能是: - remove方法可能无法正常工作 - 循环内启动的线程可能会导致问题。

I just tried this (not in Android though) and it worked fine: 我刚试过这个(不是在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();
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM