以下代码尝试完成此操作。
代码永远循环并检查是否有任何待处理的请求需要处理。如果有,它会创建一个新线程来处理请求并将其提交给执行程序。一旦所有线程都完成,它会 hibernate 60 秒并再次检查待处理的请求。
public static void main(String a[]){
//variables init code omitted
ExecutorService service = Executors.newFixedThreadPool(15);
ExecutorCompletionService<Long> comp = new ExecutorCompletionService<Long>(service);
while(true){
List<AppRequest> pending = service.findPendingRequests();
int noPending = pending.size();
if (noPending > 0) {
for (AppRequest req : pending) {
Callable<Long> worker = new RequestThread(something, req);
comp.submit(worker);
}
}
for (int i = 0; i < noPending; i++) {
try {
Future<Long> f = comp.take();
long name;
try {
name = f.get();
LOGGER.debug(name + " got completed");
} catch (ExecutionException e) {
LOGGER.error(e.toString());
}
} catch (InterruptedException e) {
LOGGER.error(e.toString());
}
}
TimeUnit.SECONDS.sleep(60);
}
}
我的问题是这些线程完成的大部分处理都与数据库有关。这个程序将在 Windows 机器上运行。当有人试图关闭或注销机器时,这些线程会发生什么?如何优雅地关闭正在运行的线程和执行器。?
最佳答案
ExecutorService 的典型有序关闭可能如下所示:
final ExecutorService executor;
Runtime.getRuntime().addShutdownHook(new Thread() {
public void run() {
executor.shutdown();
if (!executor.awaitTermination(SHUTDOWN_TIME)) { //optional *
Logger.log("Executor did not terminate in the specified time."); //optional *
List<Runnable> droppedTasks = executor.shutdownNow(); //optional **
Logger.log("Executor was abruptly shut down. " + droppedTasks.size() + " tasks will not be executed."); //optional **
}
}
});
*您可以记录执行者在等待您愿意等待的时间后仍有任务要处理。
**您可以尝试强制执行器的工作线程放弃其当前任务并确保它们不会启动任何剩余的任务。
请注意,当用户向您的 java
进程发出中断或您的 ExecutorService
仅包含守护线程时,上述解决方案将起作用。相反,如果 ExecutorService
包含尚未完成的非守护线程,则 JVM 不会尝试关闭,因此不会调用关闭 Hook 。
如果尝试将进程作为离散应用程序生命周期(而非服务)的一部分而关闭,则关闭代码不应放置在关闭 Hook 内,而应放置在程序设计终止的适当位置。
关于java - 优雅地关闭线程和执行器,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3332832/