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
线程成为可能?如果是,你可以试试这个。
我有一个使用 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
线程成为可能?如果是,你可以试试这个。