2010-03-22 125 views
3

說我有這樣的事情Java:停止運行時間過長的線程?

public void run(){ 
    Thread behaviourThread = new Thread(abstractBehaviours[i]); 
    behaviourThread.start(); 
} 

我想等到abstractBehaviours [I] run方法有兩種成品或運行5000毫秒。我怎麼做? behaviourThread.join(5000)似乎沒有這樣做afaik(我的代碼有問題,我已經把它放在那裏)。

所有抽象abstractBehaviour類當然是Runnable。我不想在每個運行方法中實現它,因爲這看起來很醜陋,而且有很多不同的行爲,我寧願將它放在調用/執行線程中,只做一次。

解決方案?第一次做這樣的事情。謝謝!

編輯:因此,中斷解決方案將是理想的(需要對AbstractBehaviour實現進行最小限度的更改)。但我需要線程停止,如果它已經完成或5000毫秒已經過去,所以像下面的東西不會工作,因爲線程可能會在父線程中的while循環之前完成。合理?任何解決這個問題的方法,我都願意從顯然啓動線程的線程中完成。

long startTime = System.currentTimeMillis(); 
behaviourThread.start(); 
while(!System.currentTimeMilis - startTime < 5000); 
behaviourThread.interrupt(); 
try { 
    behaviourThread.join(); 
} catch (InterruptedException e1) { 
    e1.printStackTrace(); 
} 

編輯:請不要介意我看到有一個Thread.isAlive()方法,解決了所有我想

+2

@約翰:與他的問題相匹配 - 除了標題,其中談到*停止*一個線程。 – 2010-03-22 22:33:48

回答

5

執行此操作的最佳方法是使用線程中斷機制。工作線程/ Runnable需要定期調用Thread.interrupted()來查看是否該停止。等式的第二部分是單獨的線程需要在工作線程上經過5000毫秒後調用Thread.interrupt()

使用線程中斷(在使用標誌一個定製溶液)的優點包括:

  • interrupted()狀態始終可用於當前線程。您不需要傳遞對象句柄或使用單例。
  • 中斷將解除阻塞某些阻塞的IO和同步請求。定製解決方案無法做到這一點。
  • 第三方Java應用程序和庫可能尊重Thread.interrupt()

編輯 - 作爲一個評論者所指出的,你可以測試是否當前線程已經使用或者Thread.interrupted()Thread.currentThread().isInterrupted()中斷。這兩種方法的主要區別在於前者清除了中斷標誌,但後者沒有。

+0

我更喜歡isInterrupted(),因爲它不依賴於中斷標誌,如中斷() – Karussell 2010-03-22 22:48:38

+0

@Karussell - 爲了記錄, isInterrupted()和中斷()依賴於「中斷標誌」。區別在於isInterrupted()不會重置該標誌。 – 2010-03-22 23:05:05

+0

我編輯了我的帖子,中斷了問題。希望現在更清楚,或者我錯過了什麼?感謝迄今爲止已經回覆的每個人,我確信一種解決方案可以工作(但需要更長時間才能更改代碼)。另一個(打斷)我可能只是失去了一些東西/正在密集。 – 2010-03-22 23:43:02

2

你不能做到這一點從外部運行方法 - run方法必須檢查一些變數,看看它應該退出。例如:

class InterruptableRunnable implements Runnable 
{ 
    private volatile boolean stop; 
    public setStop() { 
     stop = true; 
    } 

    public void run() { 
     while (!stop) 
     { 
      //do some work and occassionaly fall through to check that stop is still true 
     } 
    } 
} 

關鍵是,運行循環中的代碼偶爾會檢查停止標誌。然後,您可以連接一個定時器,在5000毫秒後將stop設置爲true。

最後,最好不要直接使用線程,而要使用優秀的併發框架。 Concurrency Tutorial是一個很好的開始和Java Concurrency in practice是優秀的書。

+0

+1,你可以通過System.currentMillis在while循環語句中包含時間限制 – Karussell 2010-03-22 22:46:31

-1

你這樣做,通過實施一個Runnable

public void run() 
{ 
    long time = System.nanoTime(), 
     end = time + 5 000 000 000; // just better formatting 
    do { 
    ...my code 

    } while (System.nanoTime() < end && myOwnCondition); 
} 
  • 中斷是沒有這樣一個很好的解決方案,因爲你需要從外面 訪問線程,它擾亂了程序流程。該線程可以隨時終止您的代碼,這使得清理變得困難。請養成讓線程運行到最後的習慣,否則它會打開令人討厭和困難的錯誤。

  • 如果你的程序是這樣的重型,你不知道那是達到了,同時結束,直到任務已經完成,我建議使用標記的突破:

    do { 
        breakout: 
        { 
        ..my code 
        if (timetest) 
         break breakout;  
        } 
        // cleanup 
        ... 
    } while (...); 
    
+0

對中斷的異常沒有響應是您在併發編程中可能犯的最大錯誤。您會注意到很多j.u.c類拋出並處理中斷的異常。在現實世界的編程中,不僅中斷異常是一個很好的解決方案,它通常是最好的解決方案如果有人正確地處理了中斷,那麼你不建議這些錯誤 – 2010-03-23 00:02:10