java - ScheduledThreadPoolExecutor 线程在完成后保留
问题描述
例程 myProcessToRun() 需要执行 100 次,但每次执行之间需要大约一秒钟的延迟。
以下 FOR 循环与 ScheduledThreadPoolExecutor 对象结合使用。
for (int n=0; n<100; n++)
{
final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(1);
executor.schedule(new Runnable() {
@Override
public void run() {
myProcessToRun();
}
}, (n+2), TimeUnit.SECONDS);
}
这实际上工作正常,但线程仍然存在。使用 JVisualVM 时,执行例程时线程数会增加 100 个线程。当例程完成时,100 个线程仍然存在。
单击“Perform GC”按钮不会清理它们,因此 Java 仍然认为它们应该存在。
如何使用上面的示例清理这些线程?
---已编辑---
我注意到 ScheduledThreadPoolExecutor 在循环中被实例化,这是一个糟糕的主意。将其移出 LOOP 后,创建的线程还不错。
尝试实施解决方案后出现意外行为。
final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(10);
for (int n=0; n<100; n++)
{
//final ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(2);
executor.schedule(new Runnable() {
@Override
public void run() {
doAddNewCondSet();
}
}, (n+2), TimeUnit.SECONDS);
}
try
{
executor.shutdown();
if (!executor.awaitTermination(400, TimeUnit.SECONDS))
executor.shutdownNow();
} catch (InterruptedException e1)
{
e1.printStackTrace();
}
使用修改后的代码,它将立即停止所有进程并关闭,并且没有执行任何操作。使用 executor.shutdown(); 注释掉并仅使用 awaitTermination(),程序刚刚挂起,几分钟后,所有进程同时启动,没有延迟,导致错误。
我怀疑我的实现是错误的。
解决方案
有多种方法可以做到这一点。您可以在此处查看其中一些: https ://www.baeldung.com/java-executor-wait-for-threads
我个人最喜欢的是 CountDownLatch:
接下来,让我们看看解决这个问题的另一种方法——使用 CountDownLatch 来表示任务完成。
我们可以用一个值来初始化它,该值表示在所有调用 await() 方法的线程被通知之前它可以递减的次数。
例如,如果我们需要当前线程等待另一个 N 个线程完成它们的执行,我们可以使用 N 初始化锁存器:
ExecutorService WORKER_THREAD_POOL
= Executors.newFixedThreadPool(10);
CountDownLatch latch = new CountDownLatch(2);
for (int i = 0; i < 2; i++) {
WORKER_THREAD_POOL.submit(() -> {
try {
// ...
latch.countDown();
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
});
}
// wait for the latch to be decremented by the two remaining threads
latch.await();
推荐阅读
- python - 是否可以自动将方法值作为参数传递给另一个方法?
- c++ - 为什么将实际数组(不是数组变量)作为参数传递给函数会引发错误?
- mysql - INTO OUTFILE 连接列
- javascript - 如何通过javascript将父子数组转换为json树结构
- spring-boot - 解析HTTP请求头时出错HTTP方法名称必须是带有HTTPS spring Boot tomcat的令牌
- sql - 如何查看表的主键?以及如何添加多个主键?
- ios - 如果 ref 不再存在,Swift -Firebase 如何触发 TransactionResult.abort()
- reactjs - 创建编辑表单时,useEffect 未更新 react-hook-form 的默认值
- ffmpeg - 从 MP3 创建碎片化的 MP4
- python - 如果字符串中有其他字符,如何匹配正则表达式模式但返回 None?