1

我有一个清单:

ArrayList 列表 = 新的 ArrayList<>();

在第一个线程上我添加元素(它很快 - 30/秒)在第二个线程上我读取它的大小并打印到文件。

第一个线程:

synchronized(list){
    list.add(PlayerPosition);
}

第二个线程:

synchronized(list){
if(list.size()>0)
    out.print(list.size() + " ");
}

它是文件的输出,只有一部分:1 1 1 3 3 5 4 6 7 7 9 11 8 9 12 10 14 16

这是错误的,因为它应该只会增加。可以有 1 1 1,但不能有 11 8。

我的程序很大,但这些只是这个列表的出现(我已经删除了一半的代码来调试它)。list.remove()整个应用程序中没有等。

我有一个问题:这可能吗,它的行为是这样的吗?否则 - 这是我在代码中某处的错。

是的,我已经尝试过 CopyOnWriteArrayList - 同样的事情。谢谢!

4

2 回答 2

1

s可能print没有按照您期望的顺序执行。将第二个线程的代码更改为以下内容:

synchronized(list){
    if (list.size() > 0) {
        synchronized (out) {
            out.print(list.size() + " ");
            out.flush();
        }
    }
}

OutputStream正在向终端(或文件或其他内容)写入字符。在没有同步out和刷新的情况下,当线程 2 告诉OutputStream打印时,可能是之前的打印还没有完成。同步和刷新强制线程 2 等到所有字符都实际写入终端后再继续。

于 2015-12-28T21:49:00.677 回答
1

您可以通过以下几种方式改进代码。首先,您不必自己实现同步原语。Java 已经内置了 SynchronizedList。请参阅Collections.synchronizedList(list)。这应该是您删除列表基础同步块的全部内容。

对于打印,另一个答案是正确的,不能保证跨线程的文件写入将按顺序发生。例如,线程 1 可能会写入8打印流,然后线程 2 会写入11. 如果线程 2 刷新然后线程 1 刷新,则生成的文件将包含11... 8。按该顺序(可能在它们之间插入其他值,具体取决于刷新的其他内容)。

于 2015-12-28T22:03:36.347 回答