Java 线程和执行器的正常关闭
下面的代码试图实现这一点 代码永远循环并检查是否有任何待处理的请求。如果有,它将创建一个新线程来处理请求并将其提交给执行者。完成所有线程后,它将休眠60秒,并再次检查挂起的请求Java 线程和执行器的正常关闭,java,multithreading,Java,Multithreading,下面的代码试图实现这一点 代码永远循环并检查是否有任何待处理的请求。如果有,它将创建一个新线程来处理请求并将其提交给执行者。完成所有线程后,它将休眠60秒,并再次检查挂起的请求 public static void main(String a[]){ //variables init code omitted ExecutorService service = Executors.newFixedThreadPool(15); ExecutorCompletionServ
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);
}
}
publicstaticvoidmain(字符串a[]){
//变量初始化代码省略
ExecutorService=Executors.newFixedThreadPool(15);
ExecutorCompletionService comp=新的ExecutorCompletionService(服务);
while(true){
List pending=service.findPendingRequests();
int noPending=pending.size();
如果(无终止>0){
对于(AppRequest请求:待定){
可调用工作线程=新请求线程(something,req);
公司提交(工人);
}
}
for(inti=0;i
我的问题是这些线程所做的大部分处理都是处理数据库的。该程序将在windows计算机上运行。当有人试图关闭或注销机器时,这些线程会发生什么情况。?如何优雅地关闭正在运行的线程和执行器。书中的“”说明:
7.4。JVM关闭
JVM可以在以下两种情况下关闭:
有秩序的或突然的方式。勤务兵
关闭在最后一次启动时启动
“普通”(非戴蒙)螺纹
终止,有人呼叫System.exit,
或通过其他特定于平台的方式
(例如发送信号或点击
Ctrl-C)。[……]
7.4.1。关闭挂钩
在有序关机中,JVM首先
启动所有已注册的关闭挂钩。
关机挂钩是未启动的线程
注册于
Runtime.addShutdownHook。JVM使
不保证所使用的顺序
关闭挂钩已启动。如果有的话
应用程序线程(守护进程或
nondaemon)仍在运行
关机时间,它们继续运行
在关闭的同时
过程当所有关机挂钩都已关闭时
完成后,JVM可以选择运行
如果runFinalizersOnExit为
正确,然后停止。JVM没有任何问题
试图停止或中断任何
仍在运行的应用程序线程
停机时运行;他们是
JVM启动时突然终止
最终停止。如果关闭
钩子或终结器未完成,
然后是有序关机过程
“挂起”,JVM必须关闭
突然[……]
重要的是,
“JVM不会试图停止或中断任何在关机时仍在运行的应用程序线程;当JVM最终停止时,这些线程会突然终止。”因此,我认为,如果没有关机挂钩来进行优雅的清理,与DB的连接将突然终止(如果您使用的是框架,它们通常会提供此类关闭挂钩)。根据我的经验,当应用程序在没有此类挂钩的情况下终止时,DB的会话可以一直保持到DB超时为止。您可以在
ExecutorService
上调用shutdown()
:
启动有序关机,其中
以前提交的任务是
已执行,但不会生成新任务
接受
或者您可以调用shutdownNow()
:
试图主动阻止一切
执行任务时,会停止处理
,并返回一个列表
正在等待的任务
执行
除此之外没有任何保证
尽力阻止
处理积极执行的任务。
例如,典型的实现
将通过Thread.interrupt()取消,因此
任何未能响应的任务
中断可能永远不会终止
调用哪一个取决于您希望它停止的程度……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 **
}
}
});
最终执行人服务执行人;
Runtime.getRuntime().addShutdownHook(新线程(){
公开募捐{
executor.shutdown();
如果(!executor.awaitTermination(关机时间)){//可选*
Logger.log(“执行器未在指定时间内终止。”);//可选*
List droppedTasks=executor.shutdownNow();//可选**
Logger.log(“Executor被突然关闭。”+droppedTasks.size()+“将不执行任务”);//可选**
}
}
});
*您可以记录执行者在等待您愿意等待的时间后仍有任务要处理。**您可以尝试强制执行者的工作线程放弃其当前任务,并确保它们不会启动任何剩余的任务 请注意,当用户向
java
进程发出中断时,或者当ExecutorService
仅包含守护进程线程时,上述解决方案将起作用。相反,如果ExecutorService
包含尚未完成的非守护进程线程,JVM将不会尝试关闭,因此关闭挂钩将不会关闭e调用
如果试图作为离散应用程序生命周期(不是服务)的一部分关闭进程,则关闭代码不应放在关闭挂钩内,而应放在程序设计用于终止的适当位置。因为添加了关闭挂钩以显式调用
shutdown()
不适合我,我在谷歌的番石榴中找到了一个简单的解决方案:
.我也有类似的问题,我经常会遇到如下错误 o、 a.c.loader.Webapp
private ThreadPoolExecutor executorPool;
@PostConstruct
public void init() {
log.debug("Initializing ThreadPoolExecutor");
executorPool = new ThreadPoolExecutor(1, 3, 1, TimeUnit.SECONDS, new ArrayBlockingQueue<Runnable>(1));
}
@PreDestroy
public void destroy() {
log.debug("Shuting down ThreadPoolExecutor");
executorPool.shutdown();
}