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?
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.
See more on this question at Stackoverflow