我正在研究一个相对简单的数据库管理器,它以一种特定的方式接收大量文件,解析和编目信息。为此,我还在Swing中编写了一个简单的GUI。为了加快进程,我想对执行的可并行化部分实现多线程,以加快程序。
下面的代码位于一个名为FDBCreatePanel
的类中,一个自定义JPanel
,位于FDBManagerFrame
中,可以容纳主方法。
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();
}
}
DbManager
类中耗时的方法导致{等级} ParserType1
类中的以下代码:
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
}
}
当我监视程序的执行时,我在JVisualVM中看不到任何t1-parser-thread
(s)。看起来好像我的代码完全在单个线程上执行,忽略了新线程的启动。我是否遗漏了线程和Swing方面的内容?
答案 0 :(得分:1)
正如Jon指出的那样,你想调用start()方法来实际生成一个新的Thread,它将调用你的内联Runnable的run方法。如果你只是调用run,就像你调用任何其他方法一样,它将在同一个Thread中执行。
}, "t1-parser-thread");
t.start();
http://docs.oracle.com/javase/7/docs/api/java/lang/Thread.html
答案 1 :(得分:1)
您正在run()
中新创建的Thread
对象上调用ParserType1.init()
。这不会启动一个新线程 - 它只是在现有线程中执行线程的run()
方法。您应该改为呼叫start()
。
从根本上说,我认为Thread
完全实现Runnable
是错误的 - “这是应该执行的代码”(Runnable
)和“这是我将要执行它的方式“(Thread
)不幸被弄糊涂了。 Thread
可以组成Runnable
的事实使其更加糟糕。
Runnable runnable = new Runnable() { ... };
Thread thread = new Thread(runnable) {
// Override run here...
};
除非被覆盖的run
方法调用super.run()
,否则将忽略传递给构造函数的Runnable
。疯狂的事情。 Thread
应该(IMO)是最终的,而不是实施Runnable
,并且强制您在构建时提供Runnable
。不幸的是,现在改变已经太晚了:(
基本上,您应该从不在run()
上呼叫Thread
。至少,我记不起上次我看到它而不是它是一个错误。