如何在计划进程完成后正确终止我的 java 程序?
How to properly kill my java program when a scheduled process is done?
我有一个简单的 java 程序,用于生成元素并在特定时间每隔 X 秒将它们插入数据库中。
生成是用 scheduleAtFixedRate
完成的。只有一个。
我希望我的程序在计划任务结束时完全退出。为此,我在取消任务时使用 System.exit()
,但这是正确的做法吗?
这是我当前的代码:
public static void main(String[] args) throws InterruptedException {
c = generateDbConnection(url, user, password);
if (c != null) {
s = generateDbStatement(c);
} else {
System.out.println("ERROR");
return;
}
initialTimestamp = new Date();
TimeUnit.SECONDS.sleep(1);
generateForAnHour();
}
private final static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
/**
* Generator thread handler Uses Statement from main function
*/
public static void generateForAnHour() {
final Runnable runner = new Runnable() {
public void run() {
String[][] data = new String[numberOfIds][2];
for (int i = 0; i < numberOfIds; i++) {
data[i] = generateDevice();
insertDevice(s, data[i][0], data[i][1]);
}
quantityOfIds += numberOfIds;
}
};
final ScheduledFuture<?> generatorHandle = scheduler.scheduleAtFixedRate(runner, 0, 5, TimeUnit.SECONDS);
scheduler.schedule(new Runnable() {
public void run() {
generatorHandle.cancel(true);
System.out.println("Scheduled ID generator terminated.");
System.exit(0); //TODO Is it really correct way to do it
}
}, timeToRun, TimeUnit.SECONDS);
}
如果程序具有更多功能,我不确定这是否是停止执行程序的正确方法,但我个人认为这是一种不错的方法。 :D
因此,事实证明,ScheduledExecutorService
似乎使用其默认 ThreadFactory
创建了非守护线程,也许我们需要为其提供一个守护线程。
但是,如果我们要调用 ExecutorService#shutdown
或强制 ExecutorService#shutdownNow
,它将停止执行这两个任务,从而删除阻止应用程序结束其作业的线程:
private final static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
public static void main(String[] args) {
// Some service code here
generateForAnHour();
}
public static void generateForAnHour() {
// Some code that does work
final Runnable runner = () -> System.out.println("Running...");
final ScheduledFuture<?> generatorHandle = scheduler.scheduleAtFixedRate(runner, 0, 1, TimeUnit.SECONDS);
// Code that interrupts the worker after a specified time
scheduler.schedule(scheduler::shutdown, 5, TimeUnit.SECONDS);
}
输出:
Running...
Running...
Running...
Running...
Running...
Running...
Process finished with exit code 0
希望对您有所帮助。 :D
这个答案是 的次要答案,但它有不同的解决问题的方法,所以我认为创建一个单独的答案是足够合适的。
如果你想在未来有更多的任务,我相信这个解决方案更具扩展性并且更"correct thing"。
它为 runner
和 interrupter
创建守护线程。我认为为 interrupter
创建一个普通的线程工厂会更好,但我没能让它工作,所以最好坚持我的第一个答案...
这里generateForAnHour
return是一个Future
用来等待需要的时间
private final static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1 , new ThreadFactory() {
@Override
public Thread newThread(final Runnable r) {
Thread t = Executors.defaultThreadFactory().newThread(r);
t.setDaemon(true);
return t;
}
});
public static void main(String[] args) throws InterruptedException, ExecutionException {
// Some service code here
generateForAnHour().get();
}
public static ScheduledFuture<Boolean> generateForAnHour() {
// Some code that does work
final Runnable runner = () -> System.out.println("Running...");
final ScheduledFuture<?> generatorHandle = scheduler.scheduleAtFixedRate(runner, 0, 1, TimeUnit.SECONDS);
// Code that interrupts the worker after a specified time
return scheduler.schedule(() -> generatorHandle.cancel(false), 5, TimeUnit.SECONDS);
}
如果您不打电话给 Future#get
,最好的情况下您只会收到一个 Running...
或根本 none。
如果您决定 return runner
未来,您可能会在 get()
通话中变得令人讨厌 CancellationException
:
Exception in thread "main" java.util.concurrent.CancellationException
at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:121)
at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
at com.xobotun.Test.main(Test.java:30)
我会使用 ExecutorService::shutdown
方法作为更稳定和更容易理解的方法。 :D
我有一个简单的 java 程序,用于生成元素并在特定时间每隔 X 秒将它们插入数据库中。
生成是用 scheduleAtFixedRate
完成的。只有一个。
我希望我的程序在计划任务结束时完全退出。为此,我在取消任务时使用 System.exit()
,但这是正确的做法吗?
这是我当前的代码:
public static void main(String[] args) throws InterruptedException {
c = generateDbConnection(url, user, password);
if (c != null) {
s = generateDbStatement(c);
} else {
System.out.println("ERROR");
return;
}
initialTimestamp = new Date();
TimeUnit.SECONDS.sleep(1);
generateForAnHour();
}
private final static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
/**
* Generator thread handler Uses Statement from main function
*/
public static void generateForAnHour() {
final Runnable runner = new Runnable() {
public void run() {
String[][] data = new String[numberOfIds][2];
for (int i = 0; i < numberOfIds; i++) {
data[i] = generateDevice();
insertDevice(s, data[i][0], data[i][1]);
}
quantityOfIds += numberOfIds;
}
};
final ScheduledFuture<?> generatorHandle = scheduler.scheduleAtFixedRate(runner, 0, 5, TimeUnit.SECONDS);
scheduler.schedule(new Runnable() {
public void run() {
generatorHandle.cancel(true);
System.out.println("Scheduled ID generator terminated.");
System.exit(0); //TODO Is it really correct way to do it
}
}, timeToRun, TimeUnit.SECONDS);
}
如果程序具有更多功能,我不确定这是否是停止执行程序的正确方法,但我个人认为这是一种不错的方法。 :D
因此,事实证明,ScheduledExecutorService
似乎使用其默认 ThreadFactory
创建了非守护线程,也许我们需要为其提供一个守护线程。
但是,如果我们要调用 ExecutorService#shutdown
或强制 ExecutorService#shutdownNow
,它将停止执行这两个任务,从而删除阻止应用程序结束其作业的线程:
private final static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1);
public static void main(String[] args) {
// Some service code here
generateForAnHour();
}
public static void generateForAnHour() {
// Some code that does work
final Runnable runner = () -> System.out.println("Running...");
final ScheduledFuture<?> generatorHandle = scheduler.scheduleAtFixedRate(runner, 0, 1, TimeUnit.SECONDS);
// Code that interrupts the worker after a specified time
scheduler.schedule(scheduler::shutdown, 5, TimeUnit.SECONDS);
}
输出:
Running...
Running...
Running...
Running...
Running...
Running...
Process finished with exit code 0
希望对您有所帮助。 :D
这个答案是
如果你想在未来有更多的任务,我相信这个解决方案更具扩展性并且更"correct thing"。
它为 runner
和 interrupter
创建守护线程。我认为为 interrupter
创建一个普通的线程工厂会更好,但我没能让它工作,所以最好坚持我的第一个答案...
这里generateForAnHour
return是一个Future
用来等待需要的时间
private final static ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1 , new ThreadFactory() {
@Override
public Thread newThread(final Runnable r) {
Thread t = Executors.defaultThreadFactory().newThread(r);
t.setDaemon(true);
return t;
}
});
public static void main(String[] args) throws InterruptedException, ExecutionException {
// Some service code here
generateForAnHour().get();
}
public static ScheduledFuture<Boolean> generateForAnHour() {
// Some code that does work
final Runnable runner = () -> System.out.println("Running...");
final ScheduledFuture<?> generatorHandle = scheduler.scheduleAtFixedRate(runner, 0, 1, TimeUnit.SECONDS);
// Code that interrupts the worker after a specified time
return scheduler.schedule(() -> generatorHandle.cancel(false), 5, TimeUnit.SECONDS);
}
如果您不打电话给 Future#get
,最好的情况下您只会收到一个 Running...
或根本 none。
如果您决定 return runner
未来,您可能会在 get()
通话中变得令人讨厌 CancellationException
:
Exception in thread "main" java.util.concurrent.CancellationException
at java.base/java.util.concurrent.FutureTask.report(FutureTask.java:121)
at java.base/java.util.concurrent.FutureTask.get(FutureTask.java:191)
at com.xobotun.Test.main(Test.java:30)
我会使用 ExecutorService::shutdown
方法作为更稳定和更容易理解的方法。 :D