use*_*101 34 java multithreading
下面这段代码试图帮助这个.
代码永远循环并检查是否有任何待处理的请求要处理.如果有,则创建一个新线程来处理请求并将其提交给执行程序.完成所有线程后,它会休眠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);
}
}
Run Code Online (Sandbox Code Playgroud)
我的问题是这些线程完成的大部分处理都是处理数据库的.这个程序将在Windows机器上运行.当有人试图关闭或注销机器时,这些线程会发生什么.如何正常关闭正在运行的线程以及执行程序.
Tim*_*der 61
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 **
}
}
});
Run Code Online (Sandbox Code Playgroud)
*您可以在等待您愿意等待的时间后记录执行程序仍有任务要处理.
**您可以尝试强制执行程序的工作线程放弃当前任务,并确保它们不启动任何其余任务.
请注意,当用户向您的java进程发出中断或您的ExecutorService唯一包含守护程序线程时,上述解决方案将起作用.相反,如果ExecutorService包含尚未完成的非守护程序线程,则JVM将不会尝试关闭,因此不会调用关闭挂钩.
如果尝试将进程作为离散应用程序生命周期(而不是服务)的一部分关闭,则不应将关闭代码放在关闭挂钩内,而应放在程序设计为终止的适当位置.
" Java Concurrency in Practice " 一书指出:
7.4.JVM关闭
JVM可以以有序或突然的方式关闭.当最后一个"正常"(nondaemon)线程终止有序关机开始,有人调用System.exit,或者其他特定于平台的方式(如发送SIGINT或按Ctrl-C).[...]
7.4.1.关机钩
在有序关闭中,JVM首先启动所有已注册的关闭挂钩.关闭挂钩是使用Runtime.addShutdownHook注册的未启动线程.JVM不保证启动关闭挂钩的顺序.如果任何应用程序线程(守护程序或非守护程序)仍在关闭时运行,它们将继续与关闭进程同时运行.当所有关闭挂钩都已完成时,如果runFinalizersOnExit为true,则JVM可以选择运行终结器,然后停止.JVM不会尝试停止或中断在关闭时仍在运行的任何应用程序线程; 当JVM最终停止时,它们会突然终止.如果关闭挂钩或终结器没有完成,那么有序关闭进程"挂起" 并且必须突然关闭JVM.[...]
重要的一点是, "JVM不会尝试停止或中断任何仍在关闭时运行的应用程序线程;当JVM最终停止时,它们会突然终止." 所以我想给DB连接会突然终止,如果没有关闭挂钩在那里做一个优雅的清理(如果你使用框架时,通常都会提供这样的关闭挂钩).根据我的经验,数据库的会话可以保留,直到应用程序的数据库等等超时.没有这样的钩子就终止了.
小智 5
由于添加一个关闭钩子来显式调用shutdown()对我来说不起作用,我在Google的Guava中找到了一个简单的解决方案:
com.google.common.util.concurrent.MoreExecutors.getExitingExecutorService.