【问题标题】:Java execute multiple Threads and wait for completion [duplicate]Java执行多个线程并等待完成[重复]
【发布时间】:2021-10-29 22:45:37
【问题描述】:

我正在编写一个小程序,它应该更新服务器上的固件。我目前这样做的方式是通过 ProcessBuilder 发出命令,执行它并使用exitCode = process.waitFor(); 等待命令完成。

其中一些固件更新可能需要几分钟,因此在设置多个系统时,如果单独进行这些固件更新可能需要数小时。

我尝试在使用 CyclicBarrier 时创建线程,以确保同时启动所有固件更新。 (见:Stackoverflow-Question: How to start two threads at “exactly” the same time

然而,我发现的问题是,在启动所有线程后,我的程序将照常继续 - 在这种情况下,将重新启动所有系统,如果它们仍在更新过程中,这可能会破坏它们固件。

如何确保在继续之前完成所有固件更新?我曾想过让程序休眠 10-15 分钟,但想要一种更可靠的方法。

【问题讨论】:

  • 是否必须等待所有服务器完成固件更新才能重新启动?或者您可以在固件更新完成后立即重新启动单个服务器吗?如果是后者,那么执行固件更新的线程也可以执行重启。另外,为什么所有固件更新都需要同时启动?
  • @Abra 两种重启选项都是可能的。我希望它们同时启动的原因如下:在任何给定服务器上,1 次固件更新平均需要 5-10 分钟。大约 2 小时后,20 次固件更新(现在正在测试)仍未完成。该软件的目标不仅是使设置过程更容易,而且更快,虽然当前的解决方案使它更容易,但它根本没有让它更快。对于 20 个系统,手动执行这些步骤大约需要半小时,而我们现在要花费 2 多个小时
  • @Abra 认为您的建议实际上可能非常有效。我试试看,谢谢!
  • 为每个服务器启动一个单独的线程。线程不必同时启动。每个线程更新单个服务器的固件。每个线程都会等待,直到其服务器的固件更新完成并且同一线程执行其服务器的重新启动。我假设所有服务器都是独立的,即每个服务器都可以独立于所有其他服务器进行更新和重新启动。因此,线程无需以任何方式相互协调。
  • @Abra 假设服务器在此之后仍需要执行其他固件更新,并且在另一个更新正在运行时不应进行任何更新,您的方法是否仍然有效?在继续下一步之前,我的程序如何知道所有服务器都已完成更新?

标签: java multithreading concurrency java-threads


【解决方案1】:

除了屏障之外,您还可以使用CountDownLatch。将CountDownLatch 传递给每个线程,一旦固件更新完成,只需调用闩锁上的倒计时。在您的主线程中,启动所有线程后,您可以通过调用latch.await 等待,它会一直等待,直到所有其他线程完成。您可以找到一个示例here

您甚至可以使用 CountDownLatch 和 1 作为发令枪的计数,这样就无法使用 CyclicBarrier

【讨论】:

    【解决方案2】:

    您需要Thread.join() 方法。看例子:

    public static void main(String[] args) throws InterruptedException {
            Runnable sleepTwoSeconds = () -> {
                try {
                    Thread.sleep(2000);
                    System.out.println("Sleeping finished");
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            };
            Thread t1 = new Thread(sleepTwoSeconds);
            t1.start();
            Thread t2 = new Thread(sleepTwoSeconds);
            t2.start();
            t1.join();
            t2.join();
            System.out.println("Main thread continue.");
    
        }
    

    “如何确保在继续之前完成所有固件更新?”在 t1 和 t2 完成之前,主线程不会继续。

    【讨论】:

    • 从我读到的关于 Thread.join() (geeksforgeeks.org/joining-threads-in-java) 的内容看来,这种方法似乎只等到线程完成后再继续下一个线程。不过,我希望所有线程都在同一时间启动。
    • 不确定我们是否在同一页面上。看看编辑后的答案。直到 t1 和 t2 没有完成,主线程才会继续。这就是你要找的吗?
    • 抱歉,我想我误解了 .join() 方法的用法。感谢您的帮助!
    猜你喜欢
    • 2014-03-18
    • 2011-06-09
    • 2012-04-09
    • 2018-06-21
    • 2019-02-23
    • 1970-01-01
    • 2021-06-21
    • 2011-05-10
    相关资源
    最近更新 更多