如何知道线程需要完成的确切时间

how to know the exact time thread requires to finish

我有两个线程 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")
}

如果你用Java8,你可以用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();

可以找到很好的介绍 here

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

如果您不能使用 Java8 中的 CompletableFuture 并且您需要等到所有提交到池的可运行程序都被执行,那么您可以在 [=15] 上使用 invokeAll =] 如下所示。

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

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

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

这在 Java 6、7 和 8 中可用;以前的版本也可能有。更多详情 here