gpt4 book ai didi

java - 如何在 Java/Scala 中中断提交给 newSingleThreadExecutor 的线程?

转载 作者:行者123 更新时间:2023-12-01 16:48:37 25 4
gpt4 key购买 nike

鉴于我有以下测试代码:

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 秒。如果超过时间限制,则应立即中断相应的线程。为了中断该线程,我在 catch TimeoutException 时尝试了两种方法:

f.cancel(true)

service.shutdownNow()

但是根据我的测试,以上方法都无法中断线程。

所以我想知道是否有方法强制中断线程。

enter image description here

最佳答案

根据 JavaDocs Future#cancelExecutorService#shutdownNow ,典型的实现是这些方法会导致底层线程中断。

If the task has already started, then the mayInterruptIfRunning parameter determines whether the thread executing this task should be interrupted in an attempt to stop the task.

There are no guarantees beyond best-effort attempts to stop processing actively executing tasks. For example, typical implementations will cancel via Thread.interrupt(), so any task that fails to respond to interrupts may never terminate.

特别注意最后一条评论。通过 Thread#interrupt 线程中断方法是一个合作过程。当一个线程中断另一个线程时,会导致设置目标线程的中断状态。此外,如果目标线程在某些特定方法中被阻止,那么该线程将遇到 InterruptedException .

如果目标线程中执行的代码既不通过 Thread#isInterrupted 定期检查中断状态,方法也不调用阻塞方法并处理 InterruptedException,则中断实际上不执行任何操作。该代码在中断过程中不配合,因此尽管线程中断,但实际上无法将其关闭。

//Given that sum() is written by others and I cannot change it.

理想情况下,将更改旨在在后台线程中执行的长时间运行的代码以配合线程中断。在您的示例中,一种可行的技术是更改 sum 以在 for 循环的每 N 次迭代中检查 Thread#isInterrupted,如果中断,中止循环。然后,它可以抛出异常来指示它未完成,或者可能返回一些哨兵 BigInt 值来指示中止(如果合适)。

如果调用的代码确实无法更改,则无法通过线程中断来停止它。您可能会使用 daemon threads这样至少这些线程不会在关闭期间阻止 JVM 退出。

关于java - 如何在 Java/Scala 中中断提交给 newSingleThreadExecutor 的线程?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45106542/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com