我有一个清单:
ArrayList list = new 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 - 同样的事情。 谢谢!
答案 0 :(得分:1)
print
可能没有按照您期望的顺序执行。将第二个线程的代码更改为以下内容:
synchronized(list){
if (list.size() > 0) {
synchronized (out) {
out.print(list.size() + " ");
out.flush();
}
}
}
您的OutputStream
正在将字符写入终端(或文件或其他内容)。如果没有out
上的同步和刷新,当线程2告诉OutputStream
打印时,之前的打印可能尚未完成。同步和刷新强制线程2等到所有字符实际写入终端后再继续。
答案 1 :(得分:1)
您可以通过以下几种方式改进代码。首先,您不必自己实现同步原语。 Java已经内置了SynchronizedList。请参阅Collections.synchronizedList(list)
。这应该是你要删除列表基础同步块。
对于打印,另一个答案是正确的,不能保证跨线程的文件写顺序会发生。例如,线程1可能会将8
写入打印流,然后线程2会写入11
。如果线程2刷新然后线程1刷新,则生成的文件将包含11
... 8
。按此顺序(在它们之间插入可能的其他值取决于刷新的其他内容)。