Reputation: 6562
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
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
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