2014-02-18 29 views
0

我正在研究一個相對簡單的數據庫管理器,它以特定的方式接收大量文件,解析和編目信息。爲此,我還在Swing中編寫了一個簡單的GUI。爲了加速進程,我想實現多線程執行的可並行化部分,以加速程序。線程無法在Swing應用程序中啓動

下面的代碼位於一個名爲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的東西?

+2

你的'ParserType1.init'方法不會啓動一個新的線程,當我懷疑你想調用'start'時,它調用'Thread'對象的'run' ... –

+0

@JonSkeet很好的捕獲...雖然我不得不問爲什麼'run()'和'start()'?我的意思是有什麼理由爲什麼會調用'run()'而不是'start()' – posdef

+1

做過線程的人犯了這個錯誤。;) – jeremyjjbrown

回答

1

你在ParserType1.init()調用新創建Thread對象run()。這不會啓動新線程 - 它只是在現有線程中執行線程的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。這是爲時已晚,現在來改變,遺憾的是:(

基本上,你應該永遠Thread調用run()。至少,我不記得我最後一次看到,如果沒有它是一個錯誤。

+0

有趣的是,我認爲這肯定是關鍵問題,但我現在正在重新運行一個測試,並且即使在't.start()'之後,「t1-parser-thread」也是無處可見的......特殊 – posdef

+0

@posdef:也許它開始,但很快完成? –