【问题标题】:Thread from Callable stays in waiting state. How do I kill the Thread?Callable 中的线程保持等待状态。如何杀死线程?
【发布时间】:2019-10-13 11:59:00
【问题描述】:

有很多类似的问题,但没有对我有用的解决方案。

我有一个需要运行一段时间的 Callable。在执行 Call 方法期间,它必须定期在 while 条件中进行一些检查,以检查它是否必须继续运行。我还希望能够从外部停止可调用(API 调用)。

下面的代码是一个简化的版本,但它有同样的问题:

当 callable 返回时,线程保持在 WAITING 状态。我如何杀死这个线程?

public class MyCallable implements Callable<Foo> {
    private AtomicBoolean stop = new AtomicBoolean(false);

    @Override
    public Foo call() {
        System.out.printf("New thread with ID=%d\n",
                Thread.currentThread().getId());
        Foo foo = new Foo();

        while (!stop.get()) {
            try {
                Thread.sleep(1000); // Sleep for some time before doing checks again
            } catch (InterruptedException e) {
            }
        }

        System.out.printf("State before returning foo: %s\n",
                Thread.currentThread().getState());
        return foo;
    }

    public void stop() {
        this.stop.set(true);
    }
}
public class Main {
    public static void main(String[] args) throws InterruptedException {
        MyCallable myCallable = new MyCallable();
        ExecutorService executorService = Executors.newFixedThreadPool(Runtime.getRuntime().availableProcessors());
        Future<Foo> future = executorService.submit(myCallable);

        printThreads();

        System.out.println("Calling stop\n");
        myCallable.stop();

        while (!future.isDone()) {
            Thread.sleep(200);
        }

        System.out.println("After future is done: ");
        printThreads();
    }

    // Helper method
    private static void printThreads() {
        List<Thread> threads = Thread.getAllStackTraces().keySet()
                .stream()
                .filter(t -> t.getName().contains("pool"))
                .collect(Collectors.toList());

        threads.forEach(t -> System.out.printf("ID=%s STATE=%s\t\n", t.getId(), t.getState()));
        System.out.println();
    }
}

这是程序的输出

【问题讨论】:

    标签: java multithreading callable


    【解决方案1】:

    您无需手动终止由ExecutorService 管理的线程。您需要优雅地关闭服务,它会终止其线程。

    executorService.shutdown();
    

    通常,线程工作者不会在单个任务完成后终止。它会移动到WAITING 状态,直到出现新任务。这些东西由ExecutorService 管理。关闭它会导致终止它负责的线程。

    【讨论】:

    • 谢谢你,这行得通!附加问题:在我的实际应用程序中,我为每个请求(每个新的可调用对象)创建一个新的 ExecutorService。这是一个好方法吗?
    • @SenneVerhaegen 我觉得这会破坏 ExecutorService 的目的。它是用来管理运行哪些东西的,不是每个 Callable 创建一个就像自己运行它们不受管理一样吗?
    • @SenneVerhaegen 通常一个ExecutorService 实例对于大多数情况来说就足够了。每次需要提交任务时,创建一次、共享并重复使用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2013-10-26
    • 2022-01-25
    • 1970-01-01
    • 1970-01-01
    • 2011-05-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多