Java 线程池,如何使用 shutdownNow() 立即停止长 运行 线程?

Java thread pool, how to stop a long running thread immediately using shutdownNow()?

我有一个使用 Executors 创建多个线程的主线程

ExecutorService executor = Executors.newFixedThreadPool(4);

每个线程都有很长的 运行ning 作业(来自另一个团队的一些遗留代码)可能 运行 几个小时。

现在我想使用

从主线程关闭
executor.shutdownNow()

我希望线程能够立即停止,我该怎么做?

在线程中,假设我们有这样的代码:

public void run() {
doA();
doB();
doC();
...
...

}

现在我的问题是,即使我调用了 shutdownNow,运行ning 线程也会 运行 结束然后停止。我想知道如何停止和退出。

您需要在 Runnable 对象实例化中包含一个标志,用于检查任务之间是否需要停止。

public void run() {
    if(timeToShutdown) return;
    doA();
    if(timeToShutdown) return;
    doB();
    /*etc*/
}

Java 中的线程在(相对)低级别运行。除了直接关闭整个 JVM 之外,手动强制停止线程的唯一方法是使用 Java 1.0/1.1 中的弃用行为,几乎没有人希望您使用它。

确实有点棘手!

我们能否利用 JDK 以 ThreadFactory 的形式提供的挂钩,当关联的线程池正在创建一个线程时,您的遗留任务将在其中查询 运行?如果是,那么为什么不在 daemon 线程中创建遗留代码 运行?我们知道,当最后一个non-daemon线程退出时,JVM也就退出了。因此,如果我们将线程池用于 运行 您的遗留任务的每个线程都设为守护线程,那么我们就有可能使 shutdownNow() 调用更具响应性:

public class LegacyCodeExecutorEx {
    public static void main(String[] args) throws InterruptedException {

        ExecutorService executor = Executors.newFixedThreadPool(2, new DaemonThreadFactory());

        executor.submit(new LegacySimulator());
        Thread.sleep(1000);
        executor.shutdownNow();
    }

    static class LegacySimulator implements Runnable {
        private final AtomicLong theLong;
        LegacySimulator() {
            theLong = new AtomicLong(1);
        }
        @Override
        public void run() {
            for (long i = 10; i < Long.MAX_VALUE; i++) {
                theLong.set(i*i);
            }
            System.out.println("Done!");
        }
    }
    static class DaemonThreadFactory implements ThreadFactory {
        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(r);
            t.setName("Daemon Thread");
            t.setDaemon(true);
            return t;
        }
    }
}

如果你玩 setDaemon(true) 行,你会看到这段代码要么立即响应主线程(即 non-daemon)的退出,要么用自己的甜蜜时间完成任务。

是否有可能使您的遗留代码-运行宁线程daemon线程成为可能?如果是,你可以试试这个。