5

好的,所以我有一个监视线程来检查 ArrayList 的大小,并在该大小大于某个数字后执行某些操作。我现在遇到的问题是大小值永远不会更新,除非我的循环中有打印语句。这是一些代码来显示我到底要做什么。

while(working) {
    // Get size function just returns the size of my list in my t class
    int size = t.getSize();
    if (size >= 10) {
        //DO STUFF
    }
}

上面的代码不起作用。它永远不会进入 if 语句。但是,这很好用:

while(working) {
    // Get size function just returns the size of my list in my t class
    int size = t.getSize();
    System.out.println(size);
    if (size >= 10) {
        //DO STUFF
    }
}

编辑:getSize() 代码:

public ArrayList<byte[]> myQueue = new ArrayList<byte[]>();

public int getSize() {
    return myQueue.size();      
}

注意:我有另一个线程正在运行,它正在更新并添加到我的 t 类中的列表中。

有什么帮助吗?当我尝试在控制台中调试时,让它吐出数字真的很烦人。

4

4 回答 4

6

如果您的工作代码和非工作代码之间唯一的变化是 println 语句,那么您几乎肯定会遇到线程问题。该System.out.println()语句添加了一个小暂停,这可能会巧合地导致它运行,但并没有解决问题。您可以执行以下操作:

try {
    Thread.sleep(10);
} catch (InterruptedException ex) {
}

...代替它并检查相同的行为,如果确实是相同的,那么这几乎证实了线程问题。然而,正如下面所指出的,它println()还会做一些其他的事情,比如导致内存屏障,所以这不是一个万无一失的测试。另一个,也许更好的检查可能是临时换出ArrayListVector这是线程安全的 - 尽管这是一个遗留集合,因此不建议在最终代码中使用。

如果是这种情况,听起来您没有ArrayList正确同步调用 -ArrayList这不是线程安全的集合。每当您读取或写入列表时,请在同步块中执行,如下所示,在列表上同步:

synchronized(list) {
    list.whatever();
}

...这将确保ArrayList一次只有一个线程可以访问,希望能解决线程问题。

于 2013-05-30T14:36:53.547 回答
5

ArrayList 未同步,或者未准备好同时在两个线程中使用。在 JLS 术语中,在一个线程中添加元素与另一个线程中的 size() 调用之间没有发生之前的关系。

最干净的解决方案是使用同步的 List 实现。您可以使用 Vector,也可以使用 Collections.synchronizedList() 在 ArrayList 周围创建一个同步包装器。

于 2013-05-30T14:39:05.503 回答
2

你的读者正在饿死作者,所以它永远没有机会运行,永远不会在你的列表中添加任何东西。

通过添加 I/O 调用(system.out.print 或 Thread.sleep),您可以将读取器线程置于允许其他线程运行的阻塞状态。

通常,像这样消耗 100% CPU 的循环是不好的。至少在循环中的某处添加一个短暂的睡眠/收益。

于 2013-05-30T15:47:08.733 回答
1

在没有看到任何其他代码的情况下,这里可能会发生许多事情。如果您给我们一个简短的可复制示例,可能会有所帮助。

就“很多事情”而言,编译器可能会在 while 循环之外重新排序大小的写入,例如

int size = t.getSize();
while(working){
   if(size >= 10){ 

   }
}

但在这一点上,这只是猜测。

于 2013-05-30T14:40:29.540 回答