我正在创建一个可以从文件加载关卡的游戏。这是在一个单独的线程上完成的,而其他一切都是在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);
}
}
我在代码中添加了两个箭头:
答案 0 :(得分:3)
我肯定会建议摆脱那个lock
对象(以及相关的依赖项)。获取actionPerformed()
中的文件列表,并构建一个副本以传递给您的runnable。避免像目前那样使用像files
这样的实例变量,因为这些变量在不必要的情况下跨线程共享。
这些synchronized
阻止对我来说是最可能的罪魁祸首。如果这不能解决您的问题,我建议您在您认为阻止的区域周围添加一些System.out.println()
来电,以便确切了解哪些电话花了这么长时间。
还要考虑使用SwingWorkers而不是自己构建新线程。这可以节省你在EDT中几个循环的线程启动时间。