使用ScheduledExecutorService时shutdown后再次请求 报RejectedExecutionException
时间: 2023-10-27 09:49:57 浏览: 211
这个错误通常发生在你尝试提交任务到已经关闭的ScheduledExecutorService中。如果你在关闭ScheduledExecutorService后再次提交任务,就会收到RejectedExecutionException异常。
你可以重新创建一个新的ScheduledExecutorService来解决这个问题,或者在调用shutdown()方法之前等待所有的任务都完成。另外,你也可以使用awaitTermination()方法等待所有任务完成后再调用shutdown()方法。
相关问题
如何可以等 ScheduledExecutorService 执行完成,再执行主线程
可以使用 `ScheduledExecutorService` 提供的 `awaitTermination` 方法,该方法会等待所有任务执行完成后再继续执行主线程。具体使用方法如下:
1. 首先在主线程中创建一个 `ScheduledExecutorService` 对象,并且提交需要执行的任务;
2. 调用 `shutdown` 方法关闭 `ScheduledExecutorService`,这样就不会再接受新的任务;
3. 调用 `awaitTermination` 方法等待任务执行完成,如果超时了会返回 `false`,否则返回 `true`。
示例代码如下:
```java
ScheduledExecutorService executor = Executors.newScheduledThreadPool(1);
executor.schedule(() -> {
// 执行任务
}, 1, TimeUnit.SECONDS);
executor.shutdown(); // 关闭 executor
try {
boolean terminated = executor.awaitTermination(5, TimeUnit.SECONDS); // 等待任务执行完成,最多等待 5 秒
if (!terminated) {
System.out.println("任务执行超时");
}
} catch (InterruptedException e) {
e.printStackTrace();
}
```
注意:在调用 `awaitTermination` 方法前必须先调用 `shutdown` 方法,否则会抛出 `RejectedExecutionException` 异常。
private static final ScheduledExecutorService executorService = Executors.newScheduledThreadPool(1);我这样定义了线程池 然后执行到public void startReconnectTask() { executorService.schedule(() -> { if (!this.session.isOpen()) { logger.info("尝试重新连接..."); connectWs(remoteUrl); } }, RECONNECT_INTERVAL, TimeUnit.MILLISECONDS); } 这个方法 报错了Caused by: java.util.concurrent.RejectedExecutionException: Task java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask@1e67d4c6 rejected from java.util.concurrent.ScheduledThreadPoolExecutor@2617d56e[Terminated, pool size = 0, active threads = 0, queued tasks = 0, completed tasks = 5] at java.util.concurrent.ThreadPoolExecutor$AbortPolicy.rejectedExecution(ThreadPoolExecutor.java:2063) at java.util.concurrent.ThreadPoolExecutor.reject(ThreadPoolExecutor.java:830) at java.util.concurrent.ScheduledThreadPoolExecutor.delayedExecute(ScheduledThreadPoolExecutor.java:326) at java.util.concurrent.ScheduledThreadPoolExecutor.schedule(ScheduledThreadPoolExecutor.java:533) at com.fld.client.websocket.PiWsClient.startReconnectTask(PiWsClient.java:88) at com.fld.client.websocket.PiWsClient.onClose(PiWsClient.java:54) ... 22 more 分析一下什么原因 然后优化一点代码
这个错误是因为线程池已经被关闭,不能再进行任务调度,所以会抛出 `RejectedExecutionException` 异常。
可以在调用 `executorService.shutdown()` 方法关闭线程池后,再调用 `executorService.awaitTermination()` 方法等待线程池中的任务执行完毕,最后再尝试执行任务。修改后的代码如下:
```
// 关闭线程池
executorService.shutdown();
try {
// 等待线程池中的任务执行完成
if (!executorService.awaitTermination(60, TimeUnit.SECONDS)) {
// 超时后仍有任务未执行完,强制关闭线程池
executorService.shutdownNow();
}
} catch (InterruptedException e) {
// 线程被中断
executorService.shutdownNow();
Thread.currentThread().interrupt();
}
// 新建线程池
ScheduledExecutorService newExecutorService = Executors.newScheduledThreadPool(1);
// 执行任务
newExecutorService.schedule(() -> {
if (!this.session.isOpen()) {
logger.info("尝试重新连接...");
connectWs(remoteUrl);
}
}, RECONNECT_INTERVAL, TimeUnit.MILLISECONDS);
```
这样就可以在关闭线程池后重新新建线程池,并执行任务。同时,加入了等待线程池中任务执行完成的逻辑,保证不会存在线程池未关闭完毕的情况。
阅读全文