【问题标题】:Java thread not stopping even after calling cancel method?即使在调用取消方法后Java线程也不会停止?
【发布时间】:2020-03-13 19:50:57
【问题描述】:
public class my {
public static void main(String[] args) throws InterruptedException {
    SomeService service = new SomeService();

    CompletableFuture<Void> async = CompletableFuture.runAsync(() -> {
        try (AutoClosableResource<SomeService> resource = new AutoClosableResource<>(service, service::disconnect)) {
            resource.get().connect();
            int i = 0;
            while (true) {
                System.out.println("--------------inside while" + i);
                Thread.sleep(500);
                i++;
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    });
    System.out.println("ouside while");
    Thread.sleep(2500);
    async.cancel(true);
    System.out.println(async.isCompletedExceptionally());
    Thread.sleep(1000);

}

public static class SomeService {
    public void connect() {
        System.out.println("connect");
    }

    public Integer disconnect() {
        System.out.println("disconnect");
        return null;
    }
}

public static class AutoClosableResource<T> implements AutoCloseable {

    private final T resource;
    private final Runnable closeFunction;

    private AutoClosableResource(T resource, Runnable closeFunction) {
        this.resource = resource;
        this.closeFunction = closeFunction;
    }

    public T get() {
        return resource;
    }

    @Override
    public void close() throws Exception {
        closeFunction.run();
    }
}

}

-------output--------


ouside while connect
--------------inside while0
--------------inside while1
--------------inside while2
--------------inside while3
--------------inside while4 true
--------------inside while5
--------------inside while6

问:为什么线程仍在运行并且打印 isCompletedExceptionally() = true 即使我手动停止它,async.cancel(true);

【问题讨论】:

  • the documentation of cancel 是否在任何时候说过它将停止另一个线程?
  • 文档说,如果尚未完成,则使用 CancellationException 完成此 CompletableFuture。
  • 并且没有说“这将停止其他正在运行的线程”。

标签: java multithreading thread-safety threadpool


【解决方案1】:

简短回答: 线程仍在运行,因为 CompletableFuture cancel 方法对 runAsync 进程没有影响,并且不会中断 Thread。

async.isCompletedExceptionally() 返回 true,因为取消抛出异常 CompletionException

详情:

来自 javadoc 关于取消方法的信息:

如果尚未完成,则使用一个完成此 CompletableFuture 取消异常。依赖的 CompletableFutures 没有 已经完成也将异常完成,带有 此 CancellationException 引起的 CompletionException

这个方法只是完成 CompletableFuture 和方法,它依赖于等待这个 CancellationException 导致的 CompletionException 的结果。方法不应该用来中断线程,而是用来完成依赖方法的工作。未来会异常完成

你应该在进程中使用这个方法,你做了一些工作,并决定取消它

因此,您的线程继续工作并因 System.exit() 而终止 查看 public static ForkJoinPool commonPool() javadoc

返回公共池实例。这个池是静态构建的; 它的运行状态不受尝试关闭或 shutdownNow 的影响。 然而,这个池和任何正在进行的处理都是自动的 在程序 System.exit 时终止。任何依赖于的程序 在程序终止前完成异步任务处理 应该在退出前调用 commonPool().awaitQuiescence。

【讨论】:

  • 非常感谢!! , 那么停止执行该线程的最佳做法是什么?
  • 你可以通过调用Thread.interrupt来停止线程,或者如果你使用executors,你可以调用shutdownNow方法。
  • 但通常不需要从外部停止线程。但是如果你需要这个,请阅读 Java Concurrency in Practice,第 7 章 Cancellation and Shutdown 一书
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-26
  • 1970-01-01
  • 2013-12-18
相关资源
最近更新 更多