java - 为什么由 ScheduledExecutorService.schedule() 启动的线程永远不会终止?

标签 java concurrency

当我通过调用 ScheduledExecutorService.schedule() 创建线程时,它在执行计划任务后永远不会终止。

例如下面的程序永远不会退出:

public static void main(String[] args) {
  ScheduledFuture scheduledFuture = 
      Executors.newSingleThreadScheduledExecutor().schedule(new Callable() {

    public Void call() {
      doSomething();
      return null;
    }

  }, 1, TimeUnit.SECONDS);
}

public static void doSomething() {
}

这是 JDK 错误,还是我错过了什么?

最佳答案

计划任务正在执行或正在等待执行。

如果任务正在等待执行,future.cancel() 将阻止它被执行(取消(真)/取消(假))。

如果任务已经在执行,future.cancel(false) 将无效。 future.cancel(true) 将中断正在执行该任务的线程。 这是否会产生任何影响取决于您,谁将执行该任务。任务可能会或可能不会响应中断,具体取决于实现。

为了使您的任务响应取消,您必须实现 doSomething() 以便它响应中断。

基本上有两种方法可以做到这一点:

1.检查逻辑中的中断标志

public void doSomething(){
    stuff();
    //Don't use Thread.interrupt()
    if(Thread.currentThread().isInterrupted()){
        // We have an interruption request, possibly a cancel request
        //Stop doing what you are doing and terminate.
        return;
    }
    doLongRunningStuff();
}  

您必须偶尔检查中断标志,如果被中断,请停止您正在做的事情并返回。请务必使用 Thread.isInterrupted() 而不是 Thread.interrupt() 进行检查。

2.Act On Interrupted exception

public void doSomething(){
    try{
        stuff();
    }catch(InterruptedException e){
        // We have an interruption request, possibly a cancel request

        // First, preserve Interrupted Status because InterruptedException clears the 
        // interrupted flag
        Thread.currentThread.interrupt();

        // Now stop doing your task and terminate
        return;
    }

    doLongRunningStuff();
}

当你有任何抛出 InterruptedException 的方法时,一定要停止你正在做的事情并在抛出一个时终止。

以这种方式实现方法后,您可以调用 future.cancel(true) 来取消正在运行的任务的执行。

关于java - 为什么由 ScheduledExecutorService.schedule() 启动的线程永远不会终止?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2903342/

相关文章:

java - 从数组内的类调用方法

java - 如何在 Spring MVC REST channel 中获取登录的用户名/主体?

java - 如何在 Java 中获取 XACML 控制台打印

go - 启动 goroutine(即调用 'go')会失败吗?

java - 在 java 中执行 Axis2 webservice 客户端时响应代码为 null 但 webservice 在服务器端成功执行

java - Firestore凭据问题: Firebase app [default] already exists

concurrency - Go 中的增量运算符在 x86 上是原子的吗?

python - SQLite 与 Python 并发?

java - 持久 HashMap 、并发 JDBM

java - java servlet 中多个线程访问的变量是否需要声明为 volatile?