1

我有两个线程 t1 和 t2。他们都做了一些计算,我试图阻止主线程直到 t1 和 t2 完成。我使用 .awaitTermination() 如下所示,但问题是,尽管它是一个 if 语句,但 .awaitTermination() 进入无限循环。

请帮我找出正在发生的事情。我应该在不知道 t1 和 t2 需要完成的确切时间的情况下指定时间量吗?

 executor.execute(new RunnableClass(bgr,3))
 executor.execute(new RunnableClass(bgr,7))
 executor.shutdown();

if (executor.awaitTermination(3, TimeUnit.SECONDS)) {
    print("terminated")
}
4

3 回答 3

5

如果您使用 Java 8,则可以CompletableFuture<T>改用。他们定义了一些有用的方法,例如 join 以等待它们的执行并将它们链接在一起。您的示例如下所示:

final CompletableFuture<Void> future1 = CompletableFuture.runAsync(new RunnableClass(bgr, 3), executor);
final CompletableFuture<Void> future2 = CompletableFuture.runAsync(new RunnableClass(bgr, 7), executor);
CompletableFuture.allOf(future1, future2).join(); // blocks until both finished
executor.shutdown();

可以在这里找到一个很好的介绍。

于 2015-05-03T15:10:27.433 回答
1

首先,你传递的时间awaitTermination是一个近似值,它应该总是比你完成所有任务所花费的最坏情况累积时间更多。如果它是您在这些可运行文件中进行的 Web 服务调用或 DB 调用,那么不为它们推测一些固定时间并不容易,因为它可能会根据您的站点流量而有所不同。因此,与其假设它总是会在某个确定的时间内完成,不如在开始使用这些结果之前等待所有这些可运行文件完成。

如果您不能CompletableFuture从 Java8 使用,并且需要等到所有提交到池的可运行文件都执行完毕,那么您可以像下面这样使用invokeAllExecutorService

invokeAll将阻塞主线程,直到所有提交的可调用对象都被执行。

// removing try-catch blocks for brevity
ExecutorService service = Executors.newFixedThreadPool(2);
List<Callable<Integer>> tasks = new ArrayList<>();
tasks.add(new Callable<Integer>(){
     public Integer call(){
                Thread.sleep(5000);
                System.out.println("thread1 coming out of sleep");
                return 1;
     }
});

tasks.add(new Callable<Integer>(){
    public Integer call(){
            Thread.sleep(10000);
            System.out.println("thread2 coming out of sleep");
            return 2;
    }
});

List<Future<Integer>> futures = service.invokeAll(tasks);
System.out.println("back in main");

service.shutdown();
service.awaitTermination(20,TimeUnit.SECONDS);

输出 :

thread1 coming out of sleep
thread2 coming out of sleep
back in main
于 2015-05-03T17:40:54.267 回答
0

另一种选择是使用ExecutorCompletionService. 它是在执行器服务之上创建的。它的take()方法返回下一个完成的任务的未来,如果还没有完成的任务可用,则等待。要等待所有提交的任务完成,您可以根据任务数量调用此方法。

ExecutorCompletionService ecs = new ExecutorCompletionService(executorService);
for (int index = 0 ; index < numberOfTasks ; index++) {
    ecs.take(); 
}

这在 Java 6、7 和 8 中可用;可能在以前的版本中也有。更多细节在这里

于 2015-05-04T18:04:56.863 回答