这与我之前提出的一个问题有关,答案是:
如果一个字段被多个线程访问,它应该是 volatile 或 final,或者只能使用同步块访问。否则,分配的值可能对其他线程不可见。
此外,任何在屏幕上操作像素的东西都应该从事件调度线程中运行,尽管当您使用重绘/绘制时这会被透明地处理。
因此,根据我的理解,我们需要担心像精灵在屏幕上移动的动画这样简单的东西的内存模型。
我的问题是,这种理解是否正确,而 Sun 教程示例,例如TumbleItem ( source ) 不正确?
这与我之前提出的一个问题有关,答案是:
如果一个字段被多个线程访问,它应该是 volatile 或 final,或者只能使用同步块访问。否则,分配的值可能对其他线程不可见。
此外,任何在屏幕上操作像素的东西都应该从事件调度线程中运行,尽管当您使用重绘/绘制时这会被透明地处理。
因此,根据我的理解,我们需要担心像精灵在屏幕上移动的动画这样简单的东西的内存模型。
我的问题是,这种理解是否正确,而 Sun 教程示例,例如TumbleItem ( source ) 不正确?
通常:
在步骤(2)和(3)中已经完成了正确的同步。这就是为什么步骤(1)中的结果可以在步骤(4)中看到的原因。想想你将如何实现事件队列,你会看到的。
您可以使用ThreadCheckingRepaintManager来帮助您找到违反 EDT 部分的时间(不是直接回答您的问题,但仍然很有帮助:-)。
你知道,我想你在这里可能有一点。TumbleItem 代码用于worker.isDone()
查明工作是否已完成。但是,我认为这不会导致完全“同步”。
我对 JDK 1.6 代码的解读是SwingWorker.isDone()
uses FutureTask
which 反过来使用Sync
具有 volatilestate
属性的对象。的执行路径isDone()
似乎不涉及synchronized
方法或块。
我不是新并发类的真正专家,但我认为 TumbleItem 应该worker.get()
在某个时候调用以保证正确同步。
编辑:我指的是 EDTimg
对工作人员填充的数组的使用。但是,正如@The Feast 所指出的,EDT 对初始化参数的使用似乎也存在问题。
我不确定您对 Sun 教程不正确是什么意思?
动画是通过使用 Swing Timer 完成的。当 Timer 触发时,代码在 EDT 上执行,这意味着它遵循 Swing 指南。
编辑:
是的,您的理解是正确的,从技术上讲,您应该担心内存模型。
是的,“偏移量”在技术上在两个不同的线程中更新:
a) 加载小程序时的默认线程
b)EDT“一旦”动画开始。
然而,在我看来(我可能倾向于简化事情),当加载小程序时,代码正在单个线程上执行,所发生的只是偏移值正在被初始化。由于只有一个线程在运行,因此您不必担心它会同时从多个线程更新。
现在,一旦动画开始,我们就会遇到不同的情况,因为 GUI 使用此值来控制动画,因此只能由 EDT 上的代码更新。
教程说“应该在事件调度线程上创建、查询和操作 Swing 组件”,但是我们还没有开始对 Swing 组件做任何事情,所以我认为这不是问题,但我不是线程专家。