如何知道线程需要完成的确切时间
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
我有两个线程 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