我无法使用shutdown()
和awaitTermination()
,因为在等待时可能会将新任务添加到ThreadPoolExecutor中。
所以我正在寻找一种方法,等待ThreadPoolExecutor清空它的队列并完成所有任务,而不会在此之前停止添加新任务。
如果它有任何区别,这适用于Android。
由于
更新:几周后重新访问后,我发现在这种情况下修改后的CountDownLatch对我来说效果更好。我会保留答案标记,因为它更适用于我的要求。
答案 0 :(得分:67)
如果您有兴趣知道某个任务何时完成,或某一批任务,您可以使用ExecutorService.submit(Runnable)
。调用此方法将返回一个Future
对象,该对象可放置在Collection
中,然后主线程将针对每个对象调用Future.get()
进行迭代。这将导致主线程暂停执行,直到ExecutorService
处理完所有Runnable
任务为止。
Collection<Future<?>> futures = new LinkedList<Future<?>>();
futures.add(executorService.submit(myRunnable));
for (Future<?> future:futures) {
future.get();
}
答案 1 :(得分:7)
我的方案是一个网络抓取工具,用于从网站获取某些信息然后进行处理。 ThreadPoolExecutor用于加速进程,因为可以在时间加载许多页面。因此,将在现有任务中创建新任务,因为爬网程序将跟随每个页面中的超链接。问题是一样的:主线程不知道所有任务何时完成,并且可以开始处理结果。我用一种简单的方法来确定这一点。它不是很优雅,但在我的情况下工作:
while (executor.getTaskCount()!=executor.getCompletedTaskCount()){
System.err.println("count="+executor.getTaskCount()+","+executor.getCompletedTaskCount());
Thread.sleep(5000);
}
executor.shutdown();
executor.awaitTermination(60, TimeUnit.SECONDS);
答案 2 :(得分:5)
也许您正在寻找CompletionService来管理批量任务,另请参阅this answer。
答案 3 :(得分:3)
(这是尝试通过我自己的调整重现Thilo之前删除的答案。)
我认为您可能需要澄清您的问题,因为存在隐含的无限条件......在某些时候您必须决定关闭执行程序,并且此时它将不再接受任何更多任务。您的问题似乎暗示您要等到知道将不再提交任何其他任务,您只能在自己的应用程序代码中知道。
以下答案将允许您顺利过渡到新的TPE(无论出于何种原因),完成所有当前提交的任务,而不是拒绝新任务到新TPE。它可能会回答你的问题。 @ Thilo也可能。
假设您已经在某处定义了可见的TPE:
AtomicReference<ThreadPoolExecutor> publiclyAvailableTPE = ...;
然后您可以编写TPE交换例程。它也可以使用同步方法编写,但我认为这更简单:
void rotateTPE()
{
ThreadPoolExecutor newTPE = createNewTPE();
// atomic swap with publicly-visible TPE
ThreadPoolExecutor oldTPE = publiclyAvailableTPE.getAndSet(newTPE);
oldTPE.shutdown();
// and if you want this method to block awaiting completion of old tasks in
// the previously visible TPE
oldTPE.awaitTermination();
}
或者,如果你真的不想开玩笑想要杀死线程池,那么你的提交者方需要在某个时候处理被拒绝的任务,你可以使用null
来获得新的TPE:
void killTPE()
{
ThreadPoolExecutor oldTPE = publiclyAvailableTPE.getAndSet(null);
oldTPE.shutdown();
// and if you want this method to block awaiting completion of old tasks in
// the previously visible TPE
oldTPE.awaitTermination();
}
这可能会导致上游问题,调用者需要知道如何处理null
。
你也可以换掉一个简单拒绝每次新执行的虚拟TPE,但这相当于你在TPE上调用shutdown()
时会发生什么。
答案 4 :(得分:1)
如果您不想使用shutdown
,请按照以下方法操作:
在Future
上对提交的所有ExecutorService
个任务进行迭代,并根据get()
建议在Future
对象上阻止来电Tim Bender
查看状态
使用
之一ExecutorService
Executors
或invokeAll()
CountDownLatch
(自java 8开始) public boolean primeNumberCheck(int n) {
// exclude numbers with divisor 2 or 3
if (n % 2 == 0) {
return false;
}
if (n % 3 == 0) {
return false;
}
// all integers can be expressed as (6k + i) for some integer k and
// for i = −1, 0, 1, 2, 3, or 4;
// 2 divides (6k + 0), (6k + 2), (6k + 4); and 3 divides (6k + 3).
// so we only have to test numbers of the form 6k +- 1
int k = 1;
int i = -1;
// we only need to check candidates up to SQRT(n)
double sqrtN = Math.Sqrt(n);
int candidateDivisor = getCandidateDivisor(k, i);
while (candidateDivisor < sqrtN) {
if (n % candidateDivisor == 0) {
return false;
}
// flip i between -1 and 1
i = -i;
// when i flips back to -1, increment k
if (i < 0) {
k++;
}
candidateDivisor = getCandidateDivisor(k, i);
}
return true;
}
private int getCandidateDivisor(k, i) {
return (6 * k) + i;
}
也实现了<TextView
android:id="@+id/tv_id"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="center"
android:layout_margin="@dimen/margin_5"
android:textColor="@color/white"
/>
相关的SE问题:
答案 5 :(得分:0)
你可以在 Runner 类上调用 waitTillDone():
<div class="form-group">
<div class="input-group">
<span class="input-group-addon" id="input-group-addon-captcha"><img id="cap-img" src="captcha.php"></span>
<input id="seo-captcha" name="" class="form-control" placeholder="Please Enter Text" type="text">
<span class="input-group-addon seo-addon-right"><button class="btn btn-xs btn-q" id="reload"><span class="glyphicon glyphicon-refresh" aria-hidden="true"></span>
</button></span>
</div>
</div>
<script>
$(function() {
$('#reload').click(function(){
$('#cap-img').attr('src', 'captcha.php?' + (new Date).getTime());
});
});
</script>
要使用它,请将此gradle / maven依赖项添加到项目中:Runner runner = Runner.runner(10);
runner.runIn(2, SECONDS, runnable);
runner.run(runnable); // each of this runnables could submit more tasks
runner.waitTillDone(); // blocks until all tasks are finished (or failed)
// and now reuse it
runner.runIn(500, MILLISECONDS, callable);
runner.waitTillDone();
runner.shutdown();
有关详情,请点击此处:https://github.com/MatejTymes/JavaFixes或此处:http://matejtymes.blogspot.com/2016/04/executor-that-notifies-you-when-task.html
答案 6 :(得分:0)
尝试使用队列大小,活动任务计数如下所示
while (executor.getThreadPoolExecutor().getActiveCount() != 0 || !executor.getThreadPoolExecutor().getQueue().isEmpty()){
try {
Thread.sleep(500);
} catch (InterruptedException e) {
}
}