2011-07-06 84 views
12

我試圖阻止一個線程,但我不能這樣做:Java:如何中斷/停止線程?

public class Middleware { 

public void read() { 
    try { 
     socket = new Socket("192.168.1.8", 2001); 

     // code .. 

     Scan scan = new Scan(); 
     thread = new Thread(scan); 
     thread.start(); 

    } catch (UnknownHostException ex) { 
     ex.printStackTrace(); 

    } catch (IOException ex) { 
     ex.printStackTrace(); 
    } 
} 

class Scan extends Thread { 

    public void run() { 

     while (true) { 
      try { 
      // my code goes here 

      } catch (IOException ex) { 
       thread.currentThread().interrupt(); 
      } 
     } 
    } 
} 

public void stop() { 
    Thread.currentThread().interrupt(); 
} 

// get and setters 
} 

所以,即使當我調用方法「一站式」的線程不停止。 它保持活力。

如何中斷/停止此線程?

UPDATE (@little方法)

private void tb_startActionPerformed(java.awt.event.ActionEvent evt) {           
    Middleware middleware = new Middleware(); 

    if (tb_start.getText().equals("Start")){ 
     tb_start.setText("Stop"); 

     // starting to read rfid tags 
     middleware.read(); 
    }else{ 
     tb_start.setText("Start"); 

     // stop reading rfid tags 
     middleware.stop(); 
    } 
} 

中間件類:

public class Middleware { 

    private Scan scan; 

    public void read() { 

     scan = new Scan(); 
     scan.start(); 
    } 

    private class Scan extends Thread { 

     @Override 
     public void run() { 
      while (!Thread.currentThread().isInterrupted()) { 
       System.out.println("reading..."); 
      } 
     } 
    } 

    public void stop() { 
     if (scan != null) { 
      scan.interrupt(); 
     } 
    } 
} 

但是當我嘗試停止線程,它沒有。 上面的代碼有什麼問題?

此致敬禮, 瓦爾特恩裏克。

+0

[在Java中停止線程?](http://stackoverflow.com/questions/247455/stopping-a-thread-in-java) – KevinDTimm

回答

17

確實沒有理由需要使用volatile標誌。相反,只需使用isInterrupted()查詢線程的狀態即可。另外,你爲什麼要把你的Scan線程對象封裝到另一個線程對象中呢?這對我來說似乎完全沒有必要。

這裏是你應該做的

public class Middleware { 
    private Scan scan; 

    public void read() { 
     try { 
      // do stuff 

      scan = new Scan(); 
      scan.start(); 
     } catch (UnknownHostException ex) { 
      // handle exception 
     } catch (IOException ex) { 
      // handle exception 
     } 
    } 

    private class Scan extends Thread { 

     @Override 
     public void run() { 
      while (!Thread.currentThread().isInterrupted()) { 
       try { 
        // my code goes here 
       } catch (IOException ex) { 
        Thread.currentThread().interrupt(); 
       } 
      } 
     } 
    } 

    public void stop() { 
     if(scan != null){ 
      scan.interrupt(); 
     } 
    } 
} 

這裏是一個example。另外,我不建議延期Thread

+0

我嘗試你的方法它不適合我,我更新我的文章,讓你可以看到我在做什麼。 –

+1

@Valter Henrique,它適用於我的系統..或許你的問題在別處? – mre

+0

對不起,我做錯了什麼,它完美的作品,感謝兄弟。 =) –

10

只需從你的while return;和線程死亡,不需要調用stop()或interrupt()。如果您想在外部執行此操作,請使用此模式並致電requestStop()

class Scan extends Thread { 
    private volatile stop = false; 
    public void run() { 

     while (!stop) { 
      try { 
      // my code goes here 

      } catch (IOException ex) { 
       stop = true; 
      } 
     } 
    } 

    public void requestStop() { 
     stop = true; 
    } 

} 
+1

如果在嘗試中有阻止代碼,如等待爲了連接被接受或者scanner.nextLine()等待輸入,這個代碼還能工作嗎? –

+1

您可以在requestStop方法中將stop設置爲true後添加一個'interrupt()'調用。 –

+0

Brunings謝謝:) –

4

「的stop()許多使用都應由只修改某些變量以指示目標線程應該停止運行的代碼來代替。」 - java.lang.Thread

4

通常的辦法來阻止一個線程是有volatile標誌,然後在run方法中檢查。即

class Scan extends Thread { 
    volatile stop = false; 
    public void run() { 

     while (!stop) { 
      try { 
      // my code goes here 

      } catch (IOException ex) { 
       thread.currentThread().interrupt(); 
      } 
     } 
    } 

    public void stop(){ 
     stop = true; 
    } 
} 

然後你可以撥打scan.stop()

+0

在你的情況下,你需要設置停止爲true,而不是調用中斷 –

+0

可以是一個屬性? 所以我可以調用一個方法'停止'來改變它的值? –

+0

@Valter是的,更新來顯示這一點。 – Jim

4

如果你想中斷正在運行的線程,那麼你需要訪問線程對象。

thread = new Thread(scan); thread.start(); 然後說

thread.interrupt();

這將中斷正在運行的線程。

1

完全同意Jim ..只是爲了添加如果你的線程被阻塞在try塊 中,例如讀取數據流等,然後中斷線程或關閉 流。在這兩種情況下,應該再次喚醒線程,然後它將能夠看到「停止」布爾值的值的變化,並由於脫離run方法而自然死亡。至少這是我在我的服務器的關閉線程中殺掉了我的線程。

0
public void run() 
    { 
     while (!Thread.currentThread().isInterrupted()) 
     { 
     //do something here 
     if(condition) 
     { 
      Thread.currentThread().interrupt(); 
     } 
    } 
+2

您能否詳細說明您的答案?添加某種解釋通常是很好的形式。 – Bono

0

而不是使用Thread.stop()或Thread.interrupt(),你可以去外部鎖。基本上,當你嘗試在大多數情況下利用內部鎖時,你在線程上執行的任何中斷都是不可控制的。

重入鎖爲您提供的方法,下面

lock() 
unlock() 
tryLock() 
lockInterruptibly() 
isHeldByCurrentThread() 
getHoldCount() 

檢查下面的例子

final ReentrantLock reentrantLock = new ReentrantLock();  
    @Override 
    public void performTask() { 
     reentrantLock.lock(); 
     try { 
      System.out.println(Thread.currentThread().getName() + ": Lock acquired."); 
      System.out.println("Processing..."); 
      Thread.sleep(2000); 
     } catch (InterruptedException e) { 
      e.printStackTrace(); 
     } finally { 
      System.out.println(Thread.currentThread().getName() + ": Lock released."); 
     reentrantLock.unlock(); 
      } 
    } 

這使你的代碼優雅和處理以更好的方式中斷提到。