2012-04-09 55 views
1

我有一個方法,應該中斷一個線程,但它不是。我是否需要始終檢查while方法中斷的線程來停止線程?我怎樣才能隨時終止線程?隨時停止線程我想要

solverTh = new Thread(new Runnable() { 
     @Override 
     public void run() { 
      while(somethingistrue){ 
       //do lot of stuff here for long time 
      } 
     } 
    }); 
    solverTh.start(); 
} 

public void terminate(){ 
    if(solverTh != null){ 
     solverTh.interrupt(); 
    } 
} 

沒關係比我認爲「很多東西」是不相關的,但我會發布它比。它使openGL操作,我現在的代碼添加布爾變量「終止」,我只是想找到一個更好的解決方案: (glc是一個GLCanvas,和rotmultiplecube方法旋轉3個對象) 反正我解決了現在的問題,謝謝你的答案。

  terminated = false; 
      try { 
       Thread.sleep(2000); 
      } catch (InterruptedException ex) { 
       Logger.getLogger(BruteForce.class.getName()).log(Level.SEVERE, null, ex); 
      } 

      int colorToBeSolved = Statics.RED_BLUE_TABLE[stateToBeSolved]; 
      System.out.println(stateToBeSolved + "," + colorToBeSolved); 
      if(entities[0].getColor() != colorToBeSolved){ 
       if(terminated) return; 
       fullRotate(Statics.FIRST_ROW, Statics.DOWN); 
      } 
      if(entities[1].getColor() != colorToBeSolved){ 
       if(terminated) return; 
       fullRotate(Statics.SECOND_COL, Statics.RIGHT); 
      } 
      if(entities[2].getColor() != colorToBeSolved){ 
       if(terminated) return; 
       fullRotate(Statics.THIRD_COL, Statics.RIGHT); 
      } 
      if(entities[3].getColor() != colorToBeSolved){ 
       if(terminated) return; 
       fullRotate(Statics.SECOND_ROW, Statics.DOWN); 
      } 
      if(entities[6].getColor() != colorToBeSolved){ 
       if(terminated) return; 
       fullRotate(Statics.THIDR_ROW, Statics.DOWN); 
      } 

      for(int i = 0; i < 9; ++i){ 
       int col = i % 3; 
       int row = 3 + i/3; 
       while(entities[i].getState() != stateToBeSolved){ 
        for(int j = 0;j < 2; ++j){ 
         if(entities[i].getState() != stateToBeSolved){ 
          if(terminated) return; 
          fullRotate(col, Statics.LEFT); 
          if(terminated) return; 
          fullRotate(row, Statics.UP); 
          if(terminated) return; 
          fullRotate(col, Statics.RIGHT); 
          if(terminated) return; 
          fullRotate(row, Statics.DOWN); 
         } 
        } 
        for(int j = 0;j < 2; ++j){ 
         if(entities[i].getState() != stateToBeSolved){ 
          if(terminated) return; 
          fullRotate(col, Statics.RIGHT); 
          if(terminated) return; 
          fullRotate(row, Statics.UP); 
          if(terminated) return; 
          fullRotate(col, Statics.LEFT); 
          if(terminated) return; 
          fullRotate(row, Statics.DOWN); 
         } 
        } 
       } 
      } 
     } 

和fullrotate方法:

private void fullRotate(int selectionIndex, int direction){ 
    for(int i = 0; i < 9; ++i){ 
     glc.rotMultipleCubeSlow(selectionIndex, direction); 
     try { 
      Thread.sleep(20); 
     } catch (InterruptedException ex) { 
      terminate(); 
     } 
    } 
    glc.setMovesText(selectionIndex, direction);   
    glc.setMultipleStateAndColorsByTable(selectionIndex, direction); 
    glc.isEntitiesRight(); 
} 
+0

1)*「我怎樣才能剛剛終止線程在任何時候?「*你認爲你可以實現Java的製造商說他們不能(至少,不安全)? 2)'//在很長一段時間裏做很多事情'代碼說話比語言更響亮。爲了更快地獲得更好的幫助,請發佈[SSCCE](http://sscce.org/)。 – 2012-04-09 11:10:22

+0

你檢查:http://docs.oracle.com/javase/1.5.0/docs/guide/misc/threadPrimitiveDeprecation.html – anuragsn7 2012-04-09 11:28:55

回答

1

優雅的解決方案是修改您的fullRotate()方法拋出InterruptedException。

private void fullRotate(int selectionIndex, int direction) 
     throws InterruptedException{ 
    for(int i = 0; i < 9; ++i){ 
     glc.rotMultipleCubeSlow(selectionIndex, direction); 
     Thread.yield(); 
    } 
    glc.setMovesText(selectionIndex, direction);   
    glc.setMultipleStateAndColorsByTable(selectionIndex, direction); 
    glc.isEntitiesRight(); 
} 
  • 當你調用了Thread.interrupt()你造成任何InterruptedException的那把它的方法被調用時,你的情況Thread.sleep()方法或Thread.yield()。這意味着最好的方法是使用它來實際中斷計算。如果你想要立即迴應你的Thread.interrupt()
  • 你仍然需要檢查Thread.currentThread()。isInterrupted()如果(終止)返回;或者用Thread.currentThread()。isInterrupted()檢查來代替它。刪除會很好,因爲來自fullRotate()的Thread.sleep(20)/Thread.yield()會拋出InterruptedException。如果(終止)所有的地方,也沒有所有這些代碼將更清潔。
  • 使用Thread.yield(),而不是用於了Thread.sleep(20)。顯然你不想睡覺,因爲你把20毫米。 20 milis非常接近上下文切換時間量。線程將會更多或更少地睡眠。你不希望它沒有任何理由睡得更多,所以使用yield()。

你線程的run()則變爲:

solverTh = new Thread(new Runnable() { 
    @Override 
    public void run() { 
     while(somethingistrue && 
       !Thread.currentThread().isInterrupted()) { 
      try { 
       //do lot of stuff here for long time 
      } catch (InterruptedException ex) { 
       // handle stop processing 
      } 
     } 
    } 
}); 
solverTh.start(); 

你也必須從下面取出的嘗試捕捉:

 try { 
      Thread.sleep(2000); 
     } catch (InterruptedException ex) { 
      Logger.getLogger(BruteForce.class.getName()).log(Level.SEVERE, null, ex); 
     } 
+0

確保您重置捕獲塊中的中斷狀態,否則while循環將繼續運行。 – 2012-04-09 18:23:12

+0

這聽起來好多了,非常感謝!我會嘗試 – 2012-04-10 11:10:43

+0

@FerencDajka請不要忘記接受答案:) – hidralisk 2012-04-10 17:31:21

0

中斷線程的唯一方法是讓它退出本身。由於死鎖的可能性,Strightforward中斷甚至沒有在Java中實現。所以,你的線程代碼必須看起來像:

solverTh = new Thread(new Runnable() { 
    @Override 
    public void run() { 
     while(somethingistrue) 
      // Do a little stuff here 
     } 
    } 
}); 
solverTh.start(); 

而且somethingistrue是一種信號的線程中斷。

+0

如果「小東西」是一個單CPU密集型任務?在完成之前,條件不會被查看 – mbatchkarov 2012-04-09 11:51:15

+0

是的,這樣的任務總是很痛苦。但無論如何,可以找到一個解決方法。例如,如果這個CPU密集型任務是單獨的進程,則線程可以在每個時間間隔檢查退出條件,並在需要時將其終止(可輕鬆處理進程)。 – 2012-04-09 12:06:33

0

唯一能夠可靠地停止從另一個線程執行的操作是操作系統。所以,沒有太多的選擇:

1)發信號線程停止自己。這個方案有點取決於線程在做什麼。如果它在另一個處理器上運行,或者阻塞呼叫,則無法解鎖,(請注意,很多阻止呼叫可以被提前返回),但可能會出現問題。

什麼是「很多東西」在做什麼?

2)使用OS調用來終止線程。這可能是一個可行的選擇,取決於線程的功能。如果在重要資源上持有公共鎖的情況下(例如,它位於malloc()的中間並鎖定了內存管理器),則有可能終止該線程,那麼您可能會遇到麻煩。你必須確定線程正在做什麼來以這種方式安全地中止它。

3)使用一個單獨的過程來運行'東西'。這顯然可以正常工作,但通常需要緩慢且痛苦的進程間通信來傳遞數據並返回結果。

4)設計應用程序,以便它不需要終止線程。有些應用程序永遠不需要終止除應用程序關閉以外的任何線程,所以沒有任何問題 - 操作系統可以阻止任何事情。在應用程序運行期間線程必須「停止」並且正在運行冗長的CPU密集型操作或在很長且可能不確定的時間段內被阻塞的情況下,通過將線程優先級設置爲最小/空閒並僅僅「孤立」讓它最終死掉是另一種常見的方法。

最糟糕的情況是線程長時間運行很多東西,它使用內存管理器或其他公共鎖,可能在一個庫中,你不知道它在做什麼,不能掛鉤並以「孤立」的方式讀寫數據意味着另一個線程無法啓動以使用數據。那時你真的很鬱悶,你可能不得不終止應用程序並重新啓動。這是最好的,以避免線程可以進入這種狀態的設計:)

5)忘記一個 - 如果線程正在使用您可以獲取的數據,設置爲NULL,0,MaxInt或其他一些像bodge可能會導致在運行很長的東西的線程中引發異常。當執行冒出很長的東西時,線程可以檢查異常處理程序中的中斷狀態,並在設置時退出。

2
while(somethingistrue !Thread.currentThread().isInterrupted()){ 
    //do lot of stuff here for long time 
} 

不必阻止IO工作。使用骯髒的技巧:重寫Thread.interrupt()關閉IO對象,導致IOException,如果處理正確可能會結束線程運行方法。

+0

+1是 - 搞鬼:)另一種是迫使一個文件夾觀察家API寫一個臨時文件到監視文件夾返回之一。可以通過打開本地客戶端連接或發送空的UDP消息來使UDP套接字讀取/ TCP接受返回。 – 2012-04-09 12:27:26

+0

該死的,這對第三方庫來說是一個非常方便的詭計!非常感謝! – parasietje 2012-04-10 13:30:04

0

當一個線程正在運行(消耗的CPU週期),那麼就不會由默認(自動地)到Thread.interrupt()響應。你將不得不編寫代碼來明確地做到這一點。

//do lot of stuff here for long time分解爲2個或更多步驟,並在這些步驟之間插入檢查Thread.currentThread().isInterrupted() - 如果爲true,則發生爆發,否則繼續。這只是實現你想要的安全方式。

這取決於長時間運行的東西是什麼,你就要來設計的步驟,並決定它最好的時候,檢查中斷和突破。