我正在創建一個遊戲,可以從文件加載關卡。這是在一個單獨的線程上完成的,而其他一切都是在Event Dispatch Thread上完成的。爲什麼我的代碼不是線程安全的?
我通過從一個非常大的測試文件加載來測試代碼,事實證明事件調度線程有時在加載關卡時沒有響應。
我似乎無法找出原因。下面是我的一些代碼:
public class LevelSelectionWrapper extends GamePanel {
...
private JList list;
private File[] files;
...
//Lock object for synchronization
private Object lock = new Object();
//Runnable for loading levels from files on a separate thread
private Runnable loader = new Runnable() {
@Override
public void run() {
synchronized(lock) {
//Load levels from files
List<Level> levels = LevelLoader.load(files); // <-------------
...
SwingUtilities.invokeLater(new ListUpdater());
}
}
};
...
private void createOpenFileButton(Container container) {
final JFileChooser fc = ...
...
//Create open button
JButton openButton = new JButton("Open file");
openButton.setFocusable(false);
openButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int returnVal = fc.showOpenDialog(LevelSelectionWrapper.this);
if(returnVal == JFileChooser.APPROVE_OPTION) {
synchronized(lock) { files = fc.getSelectedFiles(); }
//Load files on separate thread
new Thread(loader).start(); // <-------------
}
}
});
container.add(openButton);
}
}
我已經添加了兩個箭頭代碼:
- 第一個是耗時的方法(當文件確實是很大)。有時,此代碼正在運行時,事件調度線程無響應。
- 最後一個是調用runnable的地方。
在這種情況下'syncronized(lock)'是什麼?這似乎是一個壞/不必要的同步對我來說。比如,更好的辦法是在本地獲取文件列表,構建副本並將副本傳遞給加載程序,而不是使用必須鎖定的共享對象。如果我誤解了它的目的,或許你可以詳細闡述它。 – dimo414 2013-03-24 21:51:01
僅僅是這個應用程序中的EDT沒有反應,或者系統的其他部分呢? – 2013-03-24 21:51:11
@Ralf:我只使用兩個線程,EDT和工作線程。在工作線程完成之前,EDT沒有響應。 – 2013-03-24 21:53:22