1

ファイルからレベルをロードできるゲームを作成しています。これは別のスレッドで実行されますが、他のすべてはイベントディスパッチスレッドで実行されます。

非常に大きなテストファイルからロードしてコードをテストしましたが、レベルのロード中にイベントディスパッチスレッドが応答しない場合があります。

原因がわからないようです。これが私のコードの一部です:

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);
    }
}

コードに2つの矢印を追加しました。

  • 1つ目は、時間のかかる方法です(ファイルが非常に大きい場合)。このコードの実行中に、イベントディスパッチスレッドが応答しない場合があります。
  • 最後の1つは、ランナブルが呼び出される場所です。
4

1 に答える 1

3

lockそのオブジェクト(および関連する依存関係)を取り除くことを強くお勧めします。内部のファイルのリストを取得し、実行可能ファイルactionPerformed()に渡すためのコピーを作成します。filesインスタンス変数はスレッド間で不必要に共有されているため、現在のようにインスタンス変数を使用することは避けてください。

これらのsynchronizedブロックは、私にとって最も可能性の高い原因です。それでも問題が解決しない場合は、System.out.println()ブロックしていると思われるエリアの周りにいくつかの通話を追加して、どの通話に非常に時間がかかっているかを正確に確認することをお勧めします。

また、自分で新しいスレッドを作成するのではなく、SwingWorkersを使用することを検討してください。これにより、EDTでのスレッド起動時間を数サイクル節約できます。

于 2013-03-24T22:17:04.023 に答える