2012-02-02 45 views
2

我們運行了AI編程競賽,參賽者將使用我們提供的我們的API代碼AI運行在JVM上。我們通過限制他們可以對SecurityManager執行什麼操作來將它們放入沙箱中,並且在運行時他們只需設置幾個標誌,這些標誌是他們的決定。我們的系統和他們的AI之間唯一的互動是通過這些標誌,所以如果他們的線程突然死亡,對我們沒有壞影響。如何殺死不可中斷的線程?

AI計算時間太長,我們想關閉他們的線程。但是,我們無法找到保證我們會銷燬他們的線索的方法。一個可能的原因是AI進入無限循環,沒有阻塞,使得Thread.interrupt()無用。 Thread.stop()是不可靠的,因爲如果他們在try catch塊中,ThreadDeath異常將被捕獲,並且對我們來說沒有問題,因爲他們沒有觸及任何不好的東西,我們也不在乎他們是否死亡。

目前我們只是忽略他們的線程,並在他們超時後沒有他們繼續,但他們的無限循環將繼續在後臺處理,直到JVM死亡。這對我們來說是不可接受的,因爲我們將在Web服務器24/7上的後臺運行匹配項,所以我們希望獲得儘可能多的穩定性。一個想法是單獨運行每場比賽JVM,但這比我們想要的要複雜得多。

是否有任何確定的消防方式來銷燬線程?

+0

將代碼加載到您可以控制的線程中 – L7ColWinters 2012-02-02 19:38:23

+2

請更清楚地解釋爲什麼'Thread.stop()'不是一個選項。 – Tudor 2012-02-02 20:02:51

+0

根據你的API,你可以在一個單獨的進程中運行它們的代碼,並且如果它變得沒有響應就幹掉它。 – 2012-02-03 18:18:07

回答

0

在嘗試了幾件事後,我們得出結論:沒有保證的解決方案。通過在線程上調用stop(),該線程能夠捕獲ThreadDeath throwable並完全忽略它。因此,如果它在while循環中持續捕獲它,或者如果它以遞歸方式調用捕獲該方法的方法,則不能保證可以殺死它。

因爲我們沒有任何控制在這種情況下運行的代碼,並且該代碼不一定在Java中(我們也支持Jython),所以我們可以提出的最好的解決方案是產生一個線程進入循環,不斷調用suspend(),然後在線程上停止()。結果適用於大多數情況,但偶爾無法殺死惡意線程。

+0

在這種情況下,您應該考慮將應用程序的不安全部分移至單獨的JVM進程並對其進行監視。看起來這是最安全的方法之一。 – 2013-10-30 17:43:14

0

向他們提供他們必須定期調用的方法,即使在他們的計算過程中也是如此。如果你判斷他們「死了」,讓這種方法永遠睡眠。很明顯,如果他們真的死了,他不會工作,但你應該抓住大多數問題。

0

通常,不應該停止JVM中的任意線程(因此不推薦使用這些方法)。問題的根源在於,當你殺死線程時,你不知道線程在系統中的哪個位置。在最糟糕的情況下,它可能位於JVM基礎架構內的同步塊的中間,因爲未預料到意外的異常將被拋出。 (它幾乎是不可能的編寫健壯同步的代碼可以由任意點的異常被殺死。)

見關於這個問題的更多細節的高度評價答案: Are java app servers able to destroy threads? If yes, how?

你也許能夠得到在您要求AI線程退出的情況下采用合作設計。如果確實如此,那麼你很好。如果沒有,那麼你需要重新啓動JVM。