【问题标题】:how to know the exact time thread requires to finish如何知道线程需要完成的确切时间
【发布时间】:2015-05-03 14:52:29
【问题描述】:

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

【问题讨论】:

  • 这不是“确切时间”的问题,而是您使用线程的问题。
  • @Tichodroma 请让我知道如何正确设置时间以及如何使用 .awaitTermination()

标签: java multithreading executorservice countdownlatch


【解决方案1】:

如果您使用 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();

可以在here找到很好的介绍。

【讨论】:

    【解决方案2】:

    首先,您传递给awaitTermination 的时间是一个近似值,它应该始终大于完成所有任务所需的最坏情况累积时间。如果它是您在这些可运行文件中进行的 Web 服务调用或 DB 调用,那么不为它们推测一些固定时间并不容易,因为它可能会根据您网站的流量而有所不同。因此,不要只是假设它总是会在某个确定的时间完成,您只需要等待所有这些可运行文件完成,然后再开始使用这些结果。

    如果您无法使用 Java8 中的 CompletableFuture,并且需要等到所有提交到池的可运行程序都执行完毕,那么您可以在 ExecutorService 上使用 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
    

    【讨论】:

      【解决方案3】:

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

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

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-11-08
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-09-15
        相关资源
        最近更新 更多