Joo*_*kka 15 java swing thread-safety
众所周知,更新Swing GUI必须仅在EDT中完成.较少的广告是从GUI 中读取内容必须/也应该在EDT中完成.例如,让我们使用ButtonModel的isSelected()方法,它告诉(例如)ToggleButton的状态("向下"或"向上").
在我看过的每个例子中,isSelected()都是从主要或任何一个线程中自由地查询.但是当我查看DefaultButtonModel的实现时,它没有同步,并且值不是volatile.因此,严格地说,isSelected()如果从任何其他线程读取它而不是从其设置的线程(当用户按下按钮时是EDT),则可以返回垃圾.还是我弄错了?
当Bloch的Effective Java中的第66项震惊时,我最初想到这个,这个例子:
public class StopThread {
private static boolean stopRequested;
public static void main(String[] args) throws InterruptedException {
Thread backgroundThread = new Thread(new Runnable() {
public void run() {
int i = 0;
while(!stopRequested) i++;
}
});
backgroundThread.start();
TimeUnit.SECONDS.sleep(1);
stopRequested = true;
}
}
Run Code Online (Sandbox Code Playgroud)
与看起来相反,该程序永远不会终止,至少在某些机器上.stopRequested从主线程更新标志对后台线程是不可见的.可以使用同步的getter和setter或通过设置标志来修复这种情况volatile.
所以:
synchronizedor volatile),您需要确保提供适当的线程安全机制。例如,我通常编写自己的TableModel实现,通常位于我的业务对象所在List<X>的位置。X如果我打算让其他线程查询列表,我会将其设为同步Collection。还值得注意的是,我通常不会List从其他线程更新;只能查询一下。警告
尽管我在上面回答了,但我通常不会直接访问 EDT 之外的模型。正如 Carl 提到的,如果通过某些 GUI 操作调用执行更新的操作,则无需执行任何同步,因为代码已由 EDT 运行。但是,如果我希望执行一些后台处理,这将导致模型发生更改,我通常会调用 a ,然后从方法内(即在 EDT 上)SwingWorker分配结果。恕我直言,这是更干净的方法,因为该方法没有副作用。doInBackground()done()doInBackground()
| 归档时间: |
|
| 查看次数: |
1189 次 |
| 最近记录: |