[英]How to get a thread submitted to executer service and interrupt it in Java
[英]How to interrupt a thread submitted to newSingleThreadExecutor in Java/Scala?
鑒於我有以下測試代碼:
import java.util.concurrent._
object TestTime {
def main(args: Array[String]) {
println("starting....")
val service = Executors.newSingleThreadExecutor
val r = new Callable[Unit]() {
override def call(): Unit = {
//your task
val t0 = System.nanoTime
val total = sum(1000000000)
val t1 = System.nanoTime
println("Elapsed time " + (t1 - t0) / 1e9 + " secs")
println(s"total = $total")
}
}
val f = service.submit(r)
try {
// attempt the task for 2 second
f.get(2, TimeUnit.SECONDS)
} catch {
case _: TimeoutException =>
f.cancel(true)
println(s"Timeout....")
} finally {
service.shutdown()
}
println("after 2 seconds....")
for(i <- 1 to 2){
println(s"$i ...")
Thread.sleep(1000)
}
println("main thread ends...")
}
//Given that sum() is written by others and I cannot change it.
def sum(k: Int): BigInt = {
var total: BigInt = 0
for (i <- 1 to k) {
total += i
}
total
}
}
我想執行sum
最多為2秒。 如果超過時間限制,則應立即中斷相應的線程。 為了中斷該線程,我在捕獲TimeoutException
時嘗試了兩種方法:
f.cancel(true)
service.shutdownNow()
但是,根據我的測試,上述方法無法中斷線程。
所以我想知道是否有一種方法可以強制中斷線程。
根據針對Future#cancel
和ExecutorService#shutdownNow
JavaDocs的說法,典型的實現是這些方法導致中斷基礎線程。
如果任務已經開始,則mayInterruptIfRunning參數確定是否應中斷執行該任務的線程以嘗試停止該任務。
除了盡最大努力嘗試停止處理正在執行的任務之外,沒有任何保證。 例如,典型的實現將通過Thread.interrupt()取消,因此任何無法響應中斷的任務都可能永遠不會終止。
特別注意最后一條評論。 通過Thread#interrupt
方法進行的Thread#interrupt
是一個協作過程。 當一個線程中斷另一個線程時,將導致設置目標線程的中斷狀態。 另外,如果目標線程被某些特定方法阻塞,則該線程將遇到InterruptedException
。
如果在目標線程中執行的代碼既不通過Thread#isInterrupted
方法定期檢查中斷狀態,也不調用阻塞方法並處理InterruptedException
,則中斷實際上不會執行任何操作。 該代碼在中斷過程中不起作用,因此盡管有線程中斷,實際上也沒有辦法將其關閉。
//Given that sum() is written by others and I cannot change it.
理想情況下,應更改打算在后台線程中執行的長時間運行的代碼以配合線程中斷。 在您的示例中,一種可行的技術是在for
循環的每N次迭代中更改sum
以檢查Thread#isInterrupted
,如果被中斷,則中止循環。 然后,它可能會拋出異常以指示它尚未完成,或者可能返回一些前哨BigInt
值以指示中止。
如果確實不能更改被調用的代碼,那么您將無法通過線程中斷將其暫停。 您可能會使用守護程序線程,以便至少這些線程在關閉期間不會阻止JVM退出。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.