posdef
posdef

Reputation: 6562

Thread does not start in a Swing application

I am working on a relatively simple DB manager, that takes in a number of files, parses and catalogs the information in a particular fashion. I also wrote a simple GUI in Swing for this purpose. In order to speed up the process I want to implement multithreading to the parallelizable parts of the execution in order to speed up the program.

The below code sits in a class called FDBCreatePanel, a custom JPanel, that sits in a FDBManagerFrame which accommodates the main method.

private void dbCreateActionButtonActionPerformed(java.awt.event.ActionEvent evt) {//GEN-FIRST:event_dbCreateActionButtonActionPerformed

    jfc = new JFileChooser();               
    jfc.setVisible(true);
    jfc.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
    int returnVal = jfc.showSaveDialog(null);
    ((FDBManagerFrame) SwingUtilities.getRoot(this)).startProcessAnimation();

    if(returnVal == JFileChooser.APPROVE_OPTION) {
        new SwingWorker<Void,Void>(){
            @Override
            protected Void doInBackground() throws Exception {
                File dir = jfc.getSelectedFile();
                DbManager dbm = new DbManager(dir, dbNameField.getText());
                try{
                    dbm.doTimeConsumingStuff();

                } catch (SQLException e){
                    // errorhandling
                } 
            @Override
            protected void done() {
                ((FDBManagerFrame) SwingUtilities.getRoot(FDBCreatePanel.this)).endProcessAnimation();
            }
        }.execute();
    }       
}

The time consuming method in DbManager class leads to (among others) the following bits of code in the ParserType1 class:

private void init() {
    try {
        this.reader = new LineNumberReader(new FileReader(this.datfile));
        Thread t = new Thread(new Runnable(){
            @Override
            public void run() {
                Entry e;
                while((e = parseNextEntry()) != null)
                    queue.offer(e);
            }           
        }, "t1-parser-thread");
        t.run();
    } catch (FileNotFoundException e) {
        // error handling
    }
}

I do not see any t1-parser-thread(s) in JVisualVM when I monitor the execution of my program. It appears as if my code executes entirely on a single thread, ignoring the initiation of new threads. Am I missing something with respect to threading and Swing?

Upvotes: 0

Views: 97

Answers (2)

Jon Skeet
Jon Skeet

Reputation: 1502736

You're calling run() on the newly created Thread object in ParserType1.init(). That doesn't start a new thread - it just execute's the thread's run() method in the existing thread. You should be calling start() instead.

Fundamentally I think it was a mistake for Thread to implement Runnable at all - the distinction between "this is the code that should be executed" (Runnable) and "this is the way I'm going to execute it" (Thread) has been unfortunately blurred. The fact that Thread can also compose a Runnable makes it even worse.

Runnable runnable = new Runnable() { ... };
Thread thread = new Thread(runnable) {
    // Override run here...
};

Unless your overridden run method calls super.run(), the Runnable passed into the constructor is ignored. Crazy stuff. Thread should (IMO) be final, not implement Runnable, and force you to provide a Runnable at construction. It's far too late to change now, unfortunately :(

Basically, you should never be calling run() on a Thread. At least, I can't remember the last time I saw that without it being a bug.

Upvotes: 1

jeremyjjbrown
jeremyjjbrown

Reputation: 8009

As Jon Pointed out you want to call the start() method to actually spawn a new Thread which will call the run method of your inline Runnable. If you just call run it is like you called any other method and it will execute in the same Thread.

}, "t1-parser-thread");
    t.start();

http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html

Upvotes: 1

Related Questions