java中的执行者

时间:2010-11-13 19:47:06

标签: java concurrency executorservice

我试图用ExecutorService运行FixedThreadPool对象,但我遇到了问题。

我预计程序会在几纳秒内运行,但它已被挂起。我发现我需要使用Semaphore,以便队列中的项目不会累加。

有什么方法可以让我知道池的所有线程都被使用了。

基本代码......

static ExecutorService pool = Executors.newFixedThreadPool(4);
static Semaphore permits = new Semaphore(4);
try {
    permits.acquire();
    pool.execute(p);  // Assuming p is runnable on large number of objects
    permits.release();
} catch ( InterruptedException ex ) {
}

此代码被绞死,我真的不知道为什么。如何知道池当前是否正在等待所有线程完成?

3 个答案:

答案 0 :(得分:3)

默认情况下,如果您向池中提交了4个以上的任务,那么额外的任务将排队,直到线程可用。

您在评论中引用的博客使用信号量来限制可以一次排队的工作量,这对您来说不会有问题,直到排队等待成千上万的任务并开始进入有效内存。无论如何,有一种更简单的方法可以做到这一点 - 构建一个有限队列的ThreadPoolExecutor。 * 但这不是你的问题。

如果您想知道任务何时完成,请注意ExecutorService.submit()返回一个Future对象,该对象可用于等待任务完成:

Future<?> f = pool.execute(p);
f.get();
System.out.println("task complete");

如果您有多个任务并希望等待所有任务完成,请将每个Future存储在一个列表中,然后依次致电get(),或调查ExecutorService.invokeAll() (基本上在同一个方法调用中执行相同的操作)。

您还可以判断任务是否已完成:

Future<?> f = pool.execute(p);

while(!f.isDone()) {
    // do something else, task not complete
}

f.get();

最后,请注意,即使您的任务已完成,如果您未在线程池上调用shutdown(),您的程序也可能无法退出(因此似乎“挂起”);原因是线程仍在运行,等待更多的工作要做。

* 修改抱歉,我只是重新阅读了我的回答并意识到此部分不正确 - ThreadPoolExecutor 向队列提供了任务并拒绝了它们不被接受,因此有界队列与信号量方法具有不同的语义。

答案 1 :(得分:1)

您不需要信号量。

如果你挂起,可能是因为线程将自己锁定在别处。

在Debuger中运行代码,当它挂起暂停时,看看线程在做什么。

答案 2 :(得分:0)

您可以更改为使用ThreadPoolExecutor。它包含getActiveCount()方法,该方法返回活动线程的近似计数。为什么它是近似的我不确定。