Java 我如何';我会知道,ExecutorService中的所有线程都已完成执行

Java 我如何';我会知道,ExecutorService中的所有线程都已完成执行,java,multithreading,Java,Multithreading,我创建了执行器服务,如: private static final java.util.concurrent.ExecutorService EXECUTOR_SERVICE = new java.util.concurrent.ThreadPoolExecutor( 10, // core thread pool size 5, // maximum thread pool size 1, // time to wait before resiz

我创建了执行器服务,如:

private static final java.util.concurrent.ExecutorService EXECUTOR_SERVICE = new java.util.concurrent.ThreadPoolExecutor(
        10, // core thread pool size
        5, // maximum thread pool size
        1, // time to wait before resizing pool
        java.util.concurrent.TimeUnit.MINUTES, 
        new java.util.concurrent.ArrayBlockingQueue<Runnable>(MAX_THREADS, true),
        new java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy());
现在我想知道EXECUTOR_服务中的所有线程何时完成任务,以便我可以执行一些相关任务


请建议实现此目标的任何方法。

根据Java文档,提交方法的签名是
未来提交(可调用任务)

并提交一个返回值的任务以供执行,并返回一个表示任务挂起结果的未来。Future的get方法将在成功完成后返回任务的结果。 如果要立即阻止等待任务,可以使用result=exec.submit(aCallable.get())形式的构造

注意:Executors类包括一组方法,这些方法可以将一些其他常见的闭包类对象(例如PrivilegedAction)转换为可调用的形式,以便提交它们

哪个回报


根据提交方法的Java文档签名,表示任务待完成的Future是
Future submit(可调用任务)

并提交一个返回值的任务以供执行,并返回一个表示任务挂起结果的未来。Future的get方法将在成功完成后返回任务的结果。 如果要立即阻止等待任务,可以使用result=exec.submit(aCallable.get())形式的构造

注意:Executors类包括一组方法,这些方法可以将一些其他常见的闭包类对象(例如PrivilegedAction)转换为可调用的形式,以便提交它们

哪个回报

未来代表任务的待定完成您可以使用:

try  {
  executor.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
  // Report the interruptedException
}
您可以使用:

try  {
  executor.awaitTermination(1, TimeUnit.SECONDS);
} catch (InterruptedException e) {
  // Report the interruptedException
}
使用。我以前用过这个,非常成功

一种同步辅助工具,允许一个或多个线程等待,直到在其他线程中执行的一组操作完成

Javadoc链接有一个很好的例子。

使用。我以前用过这个,非常成功

一种同步辅助工具,允许一个或多个线程等待,直到在其他线程中执行的一组操作完成


Javadoc链接有一个很好的例子。

在不修改提交的任务的情况下,您可以查询ThreadPoolExecutor的内部状态,子类ThreadPoolExecutor可以根据您的需求跟踪任务完成情况,或者从任务提交中收集所有返回的
Future
s,并依次等待它们,直到它们全部完成

无特定顺序:

选项1:查询ThreadPoolExecutor的状态:

如果将引用键入到
ThreadPoolExecutor
而不是
ExecutorService
,则可以使用
ThreadPoolExecutor.getActiveCount()

来自ThreadPoolExecutor源:

/**
 * Returns the approximate number of threads that are actively executing tasks.
 * Returns:
 *   the number of threads
 **/

public int getActiveCount() {
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        int n = 0;
        for (Worker w : workers)
            if (w.isLocked())
                ++n;
        return n;
    } finally {
        mainLock.unlock();
    }
}
但是,那里提到“近似”的JavaDoc应该让您感到担心,因为给定的并发执行并不一定保证它是准确的。但是,看看代码,它确实会锁定并且假设在添加所有任务之前没有在另一个线程中查询它,那么它似乎足以测试任务的完整性

这里的一个缺点是,您需要在检查/睡眠循环中连续监视该值

选项2:子类ThreadPoolExecutor:

另一种解决方案(或者补充解决方案)是将
ThreadPoolExecutor
子类化,并重写
afterExecute
方法,以便跟踪已完成的执行并采取适当的操作。您可以设计您的子类,使其在X个任务完成后调用回调,或者剩余任务的数量降至0(因为这可能在添加所有任务之前触发),等等

选项3:收集任务未来(可能是最佳选项):

每次提交到
ExecutorService
都会返回一个
未来
,可以在列表中收集。然后,循环可以依次运行并等待每个未来,直到所有任务完成

例如

List futures=new ArrayList();
futures.add(executorService.submit(myTask1));
futures.add(executorService.submit(myTask2));
for(未来:未来){
//TODO时间限制、异常处理等。
future.get();
}

在不修改提交的任务的情况下,您可以查询ThreadPoolExecutor的内部状态,子类ThreadPoolExecutor根据您的要求跟踪任务完成情况,或者从任务提交中收集所有返回的
Future
并依次等待,直到它们全部完成

无特定顺序:

选项1:查询ThreadPoolExecutor的状态:

如果将引用键入到
ThreadPoolExecutor
而不是
ExecutorService
,则可以使用
ThreadPoolExecutor.getActiveCount()

来自ThreadPoolExecutor源:

/**
 * Returns the approximate number of threads that are actively executing tasks.
 * Returns:
 *   the number of threads
 **/

public int getActiveCount() {
    final ReentrantLock mainLock = this.mainLock;
    mainLock.lock();
    try {
        int n = 0;
        for (Worker w : workers)
            if (w.isLocked())
                ++n;
        return n;
    } finally {
        mainLock.unlock();
    }
}
但是,那里提到“近似”的JavaDoc应该让您感到担心,因为给定的并发执行并不一定保证它是准确的。但是,看看代码,它确实会锁定并且假设在添加所有任务之前没有在另一个线程中查询它,那么它似乎足以测试任务的完整性

这里的一个缺点是,您需要在检查/睡眠循环中连续监视该值

选项2:子类ThreadPoolExecutor:

另一种解决方案(或者补充解决方案)是将
ThreadPoolExecutor
子类化,并重写
afterExecute
方法,以便跟踪已完成的执行并采取适当的操作。您可以设计您的子类,使其在完成X个任务后调用回调