Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/348.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Java 线程和执行器的正常关闭_Java_Multithreading - Fatal编程技术网

Java 线程和执行器的正常关闭

Java 线程和执行器的正常关闭,java,multithreading,Java,Multithreading,下面的代码试图实现这一点 代码永远循环并检查是否有任何待处理的请求。如果有,它将创建一个新线程来处理请求并将其提交给执行者。完成所有线程后,它将休眠60秒,并再次检查挂起的请求 public static void main(String a[]){ //variables init code omitted ExecutorService service = Executors.newFixedThreadPool(15); ExecutorCompletionServ

下面的代码试图实现这一点

代码永远循环并检查是否有任何待处理的请求。如果有,它将创建一个新线程来处理请求并将其提交给执行者。完成所有线程后,它将休眠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);
    }

  }
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();
}