我有以下代码:
public class Driver {
private ExecutorService executor = Executors.newCachedThreadPool();
public static void main(String[] args) {
Driver d = new Driver();
d.run();
}
private void run() {
final Timer timer = new Timer();
final TimerTask task = new TimerTask() {
@Override
public void run() {
System.out.println("Task is running!");
}
};
Runnable worker = new Runnable() {
@Override
public void run() {
timer.scheduleAtFixedRate(task, new Date(), 5 * 1000);
}
};
Runtime.getRuntime().addShutdownHook(new Thread() {
@Override
public void run() {
System.out.println("Shutdown hook is being invoked!");
try {
if(executor.awaitTermination(20, TimeUnit.SECONDS))
System.out.println("All workers shutdown properly.");
else {
System.out.println(String.format("Maximum time limit of %s reached " +
"when trying to shut down workers. Forcing shutdown.", 20));
executor.shutdownNow();
}
} catch (InterruptedException interrupt) {
System.out.println("Shutdown hook interrupted by exception: " +
interrupt.getMessage());
}
System.out.println("Shutdown hook is finished!");
}
});
executor.submit(worker);
System.out.println("Initializing shutdown...");
}
}
当它运行时,我得到以下控制台输出:
Initializing shutdown...
Task is running!
Task is running!
Task is running!
Task is running!
Task is running!
Task is running!
Task is running!
... (this keeps going non-stop)
当我运行这个程序时,应用程序永远不会终止。相反,每隔5秒钟,我就会看到一个新的print ln"Task is running!"。我本来期望主线程到达main
方法的末尾,打印"正在初始化关机…",调用添加的关机挂钩,杀死执行器,最后打印出"关机挂钩完成了!"。
相反,"任务正在运行"只是不断地被打印出来,程序永远不会终止。这是怎么回事?
我不是专家,但AFAIK您必须终止所有非守护程序线程,以便关闭挂钩"启动"。在最初的示例中,您有3个非守护程序:
- "Main"的线程——这是你在这里想要的唯一非精灵
- 运行"TimerTask"的线程——它是由"Timer"创建的,您通过修复到
Timer(true)
来覆盖它 - 运行"worker"的线程-它由"executor"创建,为了让"executo器"创建守护程序线程,您应该创建ThreadFactory。(至少这是我知道的方式;可能还有其他方式…)
因此,我认为您应该创建一个ThreadFactory,并在初始化"executor"时使用它。
创建一个类,该类将成为ThreadFactory:
private class WorkerThreadFactory implements ThreadFactory {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r, "Worker");
t.setDaemon(true);
return t;
}
}
--重要的线路当然是setDaemon
:)
将其实例作为参数传递给newCachedThreadPool
方法:
private ExecutorService executor = Executors.newCachedThreadPool(new WorkerThreadFactory());
应用这两个变化对我来说很有用,我得到了:
Maximum time limit of 20 reached when trying to shut down workers. Forcing shutdown.
Shutdown hook is finished!
希望有帮助,
Izik
golan2@hotmail.com
它不会关闭,因为Timer()
创建并启动了一个非守护进程线程。。。这样就永远不会停止。
有两件事会导致JVM自动关闭:
- 对
System.exit()
(或Runtime.halt()
)的调用 - 最后一个剩余的非守护进程线程的终止
由于您已经创建了第二个非守护进程线程(除了运行main()
的线程之外),因此第二个条件将不满足。