2016-04-24 65 views
0

我有一個簡單的Java GUI,帶有一個開始和停止按鈕。我使用開始按鈕來運行一個線程和停止按鈕來停止它。該線程開始正常,但我不能停止按鈕。以下是一段我的代碼:無法檢索Java線程來停止它

這是圖形接口的類:

public class GridController implements ActionListener { 
// Definisco la vista 
private final GridView vista; 

acqreg acq; 
public GridController(final GridView vista) { 
    this.vista = vista; 

} 

@Override 
public void actionPerformed(final ActionEvent e) { 
    Object src = e.getSource(); 
    String ID = null; 
    String IP = null; 



    if (src == this.vista.startacqButton) {  

     // Reset di tutte le Label di errore 
     this.resetLabels(); 

     // Check degli input sui campi 
     if (this.checkAllInputs()) { 
      // CONTROLLO CAMPI ANDATO A BUON FINE 
      System.out.println("Campi Compilati Correttamente"); 

      // Inibisco le pressioni successive del bottone start 
      this.vista.startacqButton.setEnabled(false); 
      // Inibisco la modifica dei campi inseriti sul form 
      this.vista.getcbIDphidget().setEnabled(false); 
      this.vista.gettfMiscela().setEnabled(false); 
      this.vista.gettfLotto().setEnabled(false); 
      this.vista.gettfDataop().setEnabled(false); 
      // Riattivo lo stop button 
      this.vista.stopacqButton.setEnabled(true); 

      // POSSO FAR PARTIRE L'ACQUISIZIONE ----------------------------------------------------------------------------------------------------------------- 

      try { 

       // Recupero la coppia ID Scheda - IP Scheda dal file conf 
       BufferedReader phidgetip = new BufferedReader(new FileReader("PhidgetsIP.conf")); 
       String riga; 
       while ((riga = phidgetip.readLine()) != null){ 
        String[] parts = riga.split("#"); 
        String part1 = parts[0]; // ID Phidget 
        String part2 = parts[1]; // IP Phidget 


         if (part1.equals(this.vista.cbIDphidget.getSelectedItem())) { 
          ID = part1; 
          IP = part2; 


          // Creo oggetto per l'acquisizione 
          acq = new acqreg(ID , IP , vista); 
          //Avvio il thread 
          acq.start(); 

          } 

       } 
      } catch (FileNotFoundException ex) { 
       Logger.getLogger(GridController.class.getName()).log(Level.SEVERE, null, ex); 
      } catch (IOException ex) { 
       Logger.getLogger(GridController.class.getName()).log(Level.SEVERE, null, ex); 
      } 

      // Ho trovato l'ID giusto --> apro il canale di comunicazione 



     }else{ 
      System.out.println("Alcuni campi non sono stati compilati correttamente"); 
       } 


    }else if(src == this.vista.stopacqButton){ 

      // Inibisco le pressioni successive del bottone stop 
      this.vista.stopacqButton.setEnabled(false); 
      // Riattivo lo start button 
      this.vista.startacqButton.setEnabled(true); 
      // Inibisco la modifica dei campi inseriti sul form 
      this.vista.getcbIDphidget().setEnabled(true); 
      this.vista.gettfMiscela().setEnabled(true); 
      this.vista.gettfLotto().setEnabled(true); 
      this.vista.gettfDataop().setEnabled(true); 
      // Stoppo l'acquisizione 

      acq.interrupt(); 
    }                        
    } 

}

...這是運行線程「ACQ」之類的。

public class acqreg extends Thread { 

private final String ID; 
private final String IP; 
private final GridView vista; 



public acqreg(String ID , String IP, GridView vista){ 
    this.IP=IP; 
    this.ID = ID; 
    this.vista=vista; 

} 



public void run() { 



    stopped=false; 


     try{ 

      //.....do something..... 




      //dichiarazione variabili di acquisizione 
      final long start = System.nanoTime();  
      int seriale; 
      double tempDevice; 
      double tempAmbiente; 
      long prg = 1; 

        //Ciclo di acquisizione 
        while (!stopped) { 

        // ....do the long work.... 

        Thread.sleep(1000); 




        } 

    } 
     }catch(Exception ex){ 



     } 
} 

@Override 
public void interrupt() { 


stopped=true; 


} 

我覺得現在的問題是我定義線程對象 「ACQ」(在一個try catch塊):

      // Creo oggetto per l'acquisizione 
          acq = new acqreg(ID , IP , vista); 
          //Avvio il thread 
          acq.start(); 

,因爲當我嘗試停止線程:

else if(src == this.vista.stopacqButton){ 

     .......some code......... 

     // Stoppo l'acquisizione 

     acq.interrupt(); 

interrupt()方法不啓動,線程繼續運行!在調試模式下,我在線「acq.interrupt()」出現這個錯誤:

Exception in thread "AWT-EventQueue-0" java.lang.NullPointerException 

請幫幫我。非常感謝大家!

+1

你確定已經分配了acq對象。如果你在那裏得到一個空指針異常,那麼它意味着acq == null。也請清理代碼,因爲它很難讀取atm。 – mdewit

+0

除了你的NPE之外,我還會放下'stopped'變量(它必須是volatile) - 如果沒有,它實際上會導致線程繼續),並簡單地使用中斷狀態,如http:// www中的清單5所示.ibm.com/developerWorks的/庫/ J-jtp05236 / – zapl

回答

0

謝謝大家的寶貴意見,我解決了NullPointerException。問題在於acq對象的聲明,它必須是靜態的。現在線程正常工作。

1

其實有幾個問題有:

1)你的代碼格式是可怕的......至少使用一些IDE,做了intendation你。

2)你的班級命名不好。請遵守命名慣例。類名以「C」首字母開頭。

3)最好不要使用方法名「interrupt()」。更糟的是,切勿在Thread/Runnable類中重寫此方法!除非在那裏調用super.interrupt()會導致嚴重的問題! 因爲中斷()正是讓你的sleep()退出暫停狀態的一件事情。

4)至少要做一些基本的異常處理,除非你確切地知道你在做什麼,否則你應該不要忽略異常,然後應該評論它!

下面是一個有點像樣的工作線程應該看起來像一個小例子。它將所有與線程有關的東西從調用方中分離出來,並僅授予對startThread()和stopThread()方法的訪問權限。這樣,沒有任何東西可以不受外界干擾。

/** 
* This worker can only run once 
* @author JayC667 
*/ 
public class ProperThreading { 

    private final Thread  mThread   = new Thread(() -> runWorkingLoop()); // if you want worker to be able to run multiple times, move initialisation into startThread() 
    private volatile boolean mThreadStarted = false; 
    private volatile boolean mStopRequested = false; 

    private final long   mLoopSleepTime; 

    public ProperThreading(final long pLoopSleepTime /* pass more arguments here, store in members */) { 
     mLoopSleepTime = pLoopSleepTime; 
    } 

    public synchronized void startThread() { 
     if (mThreadStarted) throw new IllegalStateException("Worker Thread may only be started once and is already running!"); 
     mThreadStarted = true; 
     mThread.start(); 
    } 

    private void runWorkingLoop() { 
     while (!mStopRequested /* && other checks */) { 
      try { 
       // do the magic work here 
       Thread.sleep(mLoopSleepTime); 

      } catch (final InterruptedException e) { 
       break; 
      } catch (final Exception e) { 
       // do at least some basic handling here, you should NEVER ignore exception unless you know exactly what you're doing, and then it should be commented! 
      } 
     } 
    } 

    public synchronized void stopThread() { 
     if (!mThreadStarted) throw new IllegalStateException("Worker Thread is not even running yet!"); 
     mStopRequested = true; 
     mThread.interrupt(); 
    } 

}