Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/java/336.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

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/7/jsf/5.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 Spring引导:通过控制涉及MongoClient的终止顺序,优雅地关闭_Java_Mongodb_Multithreading_Spring Boot_Shutdown Hook - Fatal编程技术网

Java Spring引导:通过控制涉及MongoClient的终止顺序,优雅地关闭

Java Spring引导:通过控制涉及MongoClient的终止顺序,优雅地关闭,java,mongodb,multithreading,spring-boot,shutdown-hook,Java,Mongodb,Multithreading,Spring Boot,Shutdown Hook,我有一个Spring启动应用程序,它使用一个AsyncTaskExecutor(数字是预定义的)生成许多线程 线程执行一个无限循环,从一些队列和进程对象读取数据,因此我没有真正的拒绝策略机制(比如接受任务的线程池) 问题是,当应用程序关闭时,线程可能(也可能)忙于处理一个项目,其中包括使用MongoTemplate对Mongo进行操作 因此,当应用程序关闭时,MongoClient将自动被close()'d关闭,然后我从Mongo收到一些错误,如: java.lang.IllegalStateE

我有一个Spring启动应用程序,它使用一个
AsyncTaskExecutor
(数字是预定义的)生成许多线程

线程执行一个无限循环,从一些队列和进程对象读取数据,因此我没有真正的拒绝策略机制(比如接受
任务的线程池

问题是,当应用程序关闭时,线程可能(也可能)忙于处理一个项目,其中包括使用
MongoTemplate
对Mongo进行操作

因此,当应用程序关闭时,MongoClient将自动被
close()
'd关闭,然后我从Mongo收到一些错误,如:

java.lang.IllegalStateException: The pool is closed
    at com.mongodb.internal.connection.ConcurrentPool.get(ConcurrentPool.java:137)
    at com.mongodb.internal.connection.DefaultConnectionPool.getPooledConnection(DefaultConnectionPool.java:262)
    at com.mongodb.internal.connection.DefaultConnectionPool.get(DefaultConnectionPool.java:103)
    at com.mongodb.internal.connection.DefaultConnectionPool.get(DefaultConnectionPool.java:92)
    at com.mongodb.internal.connection.DefaultServer.getConnection(DefaultServer.java:85)
如何才能优雅地关闭应用程序?e、 g.在不关闭MongoClient的情况下中断线程

代码:

Bean创建:

@Bean
AsyncTaskExecutor getTaskExecutor() {
    SimpleAsyncTaskExecutor executor = new SimpleAsyncTaskExecutor();
    return executor;
}
仅通过以下方式执行:

executor.execute(runnable);

不要使用
SimpleAsyncTaskExecutor
-SimpleAsyncTaskExecutor为每个请求创建一个新线程,而应使用
ThreadPoolTaskExecutor
并配置以下两个属性

/**
 * Set whether to wait for scheduled tasks to complete on shutdown,
 * not interrupting running tasks and executing all tasks in the queue.
 * <p>Default is "false", shutting down immediately through interrupting
 * ongoing tasks and clearing the queue. Switch this flag to "true" if you
 * prefer fully completed tasks at the expense of a longer shutdown phase.
 * <p>Note that Spring's container shutdown continues while ongoing tasks
 * are being completed. If you want this executor to block and wait for the
 * termination of tasks before the rest of the container continues to shut
 * down - e.g. in order to keep up other resources that your tasks may need -,
 * set the {@link #setAwaitTerminationSeconds "awaitTerminationSeconds"}
 * property instead of or in addition to this property.
 * @see java.util.concurrent.ExecutorService#shutdown()
 * @see java.util.concurrent.ExecutorService#shutdownNow()
 */
public void setWaitForTasksToCompleteOnShutdown(boolean waitForJobsToCompleteOnShutdown) {
    this.waitForTasksToCompleteOnShutdown = waitForJobsToCompleteOnShutdown;
}

/**
 * Set the maximum number of seconds that this executor is supposed to block
 * on shutdown in order to wait for remaining tasks to complete their execution
 * before the rest of the container continues to shut down. This is particularly
 * useful if your remaining tasks are likely to need access to other resources
 * that are also managed by the container.
 * <p>By default, this executor won't wait for the termination of tasks at all.
 * It will either shut down immediately, interrupting ongoing tasks and clearing
 * the remaining task queue - or, if the
 * {@link #setWaitForTasksToCompleteOnShutdown "waitForTasksToCompleteOnShutdown"}
 * flag has been set to {@code true}, it will continue to fully execute all
 * ongoing tasks as well as all remaining tasks in the queue, in parallel to
 * the rest of the container shutting down.
 * <p>In either case, if you specify an await-termination period using this property,
 * this executor will wait for the given time (max) for the termination of tasks.
 * As a rule of thumb, specify a significantly higher timeout here if you set
 * "waitForTasksToCompleteOnShutdown" to {@code true} at the same time,
 * since all remaining tasks in the queue will still get executed - in contrast
 * to the default shutdown behavior where it's just about waiting for currently
 * executing tasks that aren't reacting to thread interruption.
 * @see java.util.concurrent.ExecutorService#shutdown()
 * @see java.util.concurrent.ExecutorService#awaitTermination
 */
public void setAwaitTerminationSeconds(int awaitTerminationSeconds) {
    this.awaitTerminationSeconds = awaitTerminationSeconds;
}
可以找到完整的列表

更多详情及


显示如何生成线程。您应该能够覆盖isInterrupted并与mongo进行优雅的断开连接。问题是,我仍然从mongo客户端收到错误,要求我在每次使用MongoTemplate时都尝试捕获非法状态异常。有没有办法绕过这个问题?这很奇怪。如果你能分享一个复制你的问题的例子(最好是github项目),那么我可以更深入地看一看,也请更新你的帖子来展示你现在拥有的东西。需要更多的细节。您可以使用@Async注释来运行任务吗?这些任务是如何安排的?您必须让spring为您管理任务。一些示例我将尝试@Async,正如您所建议的那样。当您将该方法标记为
@Async
,当调用该方法时,它将在单独的线程(从threadpool借用的线程)中运行,并由spring管理。因此,一旦spring引导关闭,它将优雅地完成执行任务的线程。您需要
@EnableAsync
来启用异步处理。
spring.task.execution.shutdown.await-termination=true
spring.task.execution.shutdown.await-termination-period=60
@Bean
public ThreadPoolTaskExecutor threadPoolTaskExecutor() {
    ThreadPoolTaskExecutor taskExecutor = new ThreadPoolTaskExecutor();
    taskExecutor.setCorePoolSize(5);
    taskExecutor.setMaxPoolSize(5); 
    taskExecutor.waitForTasksToCompleteOnShutdown(true);
    taskExecutor.setAwaitTerminationSeconds(60);
    return taskExecutor;
  }