2012-07-23 177 views
0

我有一個JRuby引擎,它可以評估一些腳本,並且如果它需要超過5秒的時間我想關閉該線程。 我想是這樣的:Java線程不會停止

class myThread extends Thread{ 
    boolean allDone = false; 

    public void threadDone() { 
     allDone = true; 
    } 

    public void run() { 
     while(true) { 
      engine.eval(myScript); 
      if(allDone) 
       return; 
     } 
    } 

(...) 

    th1 = new myThread(); 
    th1.start(); 
    try { 
     Thread.sleep(5000); 
     if(th1.isAlive()) 
      th1.threadDone(); 
    } catch(InterruptedException e) {} 

    if(th1.isAlive()) 
     System.out.println("Still alive"); 

我也試圖與th1.stop()th1.interrupt()th1.isAlive()方法retured值始終true殺死線程。

我該怎麼辦? 我想補充myScript可能是「while(1)do; end」,我不能等到它完成。所以我想要阻止這樣的腳本,並且如果它花費超過5秒鐘就殺死線程。

+0

不要'擴展線程'。這是一個衆所周知的反模式。 – 2012-07-23 12:03:31

+0

它正在運行一個腳本,對吧?所以你需要停止它運行腳本。如果將'myScript'設置爲null會發生什麼?它會立即在線程中引發異常嗎? – 2012-07-23 12:58:30

+0

不,它不。如果我將'myScript'設置爲「」,它會循環。它表現得像「while(1)do; end」。 – user1521526 2012-07-23 13:13:39

回答

2

另一種解決方案是使用內置的機制來中斷線程:

public void run() { 
    while (!Thread.currentThread().isInterrupted()) { 
     engine.eval(myScript); 
    } 
} 

... 
th1 = new myThread(); 
th1.start(); 
try { 
    Thread.sleep(5000); 
    th1.interrupt(); 
} 

這樣一來,無需一個allDone領域,未能同步,沒有任何風險。

+0

好像你可以把這個條件放入'while'而不是'true'。 – 2012-07-23 12:04:27

+0

是的,我剛剛複製並粘貼了原始代碼,但沒有太多注意,但我會解決這個問題。 – 2012-07-23 12:06:12

+1

似乎這個習慣用法是檢查'Thread.interrupted()',爲自己保存一個間接尋址,這個調用也會清除被中斷的標誌,這應該是很好的 - 只要你發現你被中斷了,你重置'interrupt'信號標誌(我在前面的問題中讀到了這個) – 2012-07-23 12:11:12

0

爲了讓你的線程可以停止,你可能需要類似的東西。

class MyTask implements Runnable { 
    public void run() { 
     try { 
      engine.eval(myScript); 
     } catch(ThreadDeath e) { 
      engine = null; // sudden death. 
     } 
    }  
} 

您可以調用Thread.stop(),但我建議您先閱讀此方法的警告。


如果你想要一個線程運行長達5秒,最簡單的解決方案是線程自行停止。

class MyTask implements Runnable { 
    public void run() { 
     long start = System.currentTimeMillis(); 
     do { 
      engine.eval(myScript); 
     } while(System.currentTimeMillis() < start + 5000); 
    }  
} 

這假定您想要重複運行engine.eval()。如果不是這種情況,你可能不得不停止()線程。它有一個很好的理由被棄用,但它可能是您唯一的選擇。

+0

Peter我只想運行engine.eval()一次。當用戶嘗試評估諸如「while(1)do; end」之類的腳本時,就會出現問題。所以我想要防止這種情況發生,如果它需要超過5秒鐘的時間就殺死線程。 – user1521526 2012-07-23 13:06:30

+0

在這種情況下,Thread.stop()是你唯一的選擇。這可能會讓您的引擎處於不一致的狀態,因此您可能需要重新創建它。 – 2012-07-23 13:08:33

+0

以及我試圖使用Thread.stop()但線程仍然活着。 (Thread.isAlive()方法返回true) – user1521526 2012-07-23 13:15:34