简体   繁体   中英

Why is my code not thread safe?

I'm creating a game where levels can be loaded from a file. This is done on a separate thread, while everything else is done on the Event Dispatch Thread.

I tested the code by loading from a really large test file, and it turns out that the Event Dispatch Thread on occasions is unresponsive while the level is being loaded.

I can't seem to figure out the cause. Here's some of my code:

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

I've added two arrows to the code:

  • The first one is the time consuming method (when the files are really large). On occasions, the Event Dispatch Thread is unresponsive while this code is running.
  • The last one is where the runnable is invoked.

I would definitely suggest getting rid of that lock object (and the associated dependencies). Get the list of files inside actionPerformed() and construct a copy to pass off to your runnable. Avoid using instance variables like files like you currently are, as those are being shared across threads unnecessarily.

These synchronized blocks are the most likely culprit to me. If that doesn't resolve your issue, I'd suggest adding some System.out.println() calls around the areas you think are blocking to try to see exactly which call(s) are taking so long.

Also consider using SwingWorkers rather than constructing a new thread yourself. That could save you a few cycles of thread-startup time in the EDT.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM