【问题标题】:Why can't I run the statements in main() after my threads stop working?为什么我的线程停止工作后我不能运行 main() 中的语句?
【发布时间】:2019-05-31 21:24:30
【问题描述】:

所以我有一个有 4 个线程的程序,所有线程都在运行。 其中 3 个线程始终在运行,即使程序完成了它的工作。 所以我创建了一些变量,让它们停止。

我将while(true) 更改为while(exit),程序运行正常。

在线程之后,我想运行一些其他语句,但前提是线程已经停止。

我尝试使用 4 个变量,exit、exit1、exit2、exit3 并将它们设置为 false。线程将完成并使这些变量为真。

在 main 中,Thread.start() 之后,如果我想打印一些东西,它不会打印。

Thread1.start();
Thread2.start();
Thread3.start();
Thread4.start();

// System.out.println("Program Ended") --> If i do this, it prints before 
// the threads

if(exit && exit2 && exit3 && exit4) {
    System.out.println("Program Ended");
    // code here 
}

有没有办法确保我只在线程停止后才运行一些语句?

【问题讨论】:

    标签: java multithreading parallel-processing


    【解决方案1】:

    Thread 类有一个方法可以为您执行此操作,join 将阻塞,直到线程完成执行。 Baeldung使用教程Thread#join

    所以你的代码应该是这样的:

    thread1.start();
    thread2.start();
    thread3.start();
    thread4.start();
    
    thread1.join();
    thread2.join();
    thread3.join();
    thread4.join();
    
    if(exit && exit2 && exit3 && exit4) {
        System.out.println("Program Ended");
    }
    

    【讨论】:

      【解决方案2】:

      作为替代方案,您应该考虑CyclicBarrierCountDownLatch
      与自定义终止线程标志相比,这些更不容易出错,通常不那么冗长且相当有效。

      有它们的特殊性,但相当接近。 CountDownLatch 关联“countDown”操作的计数器以继续进行,而 CyclicBarrier 关联调用 await() 的不同线程的计数器以应用特定处理。

      CyclicBarrier 可能看起来像:

      CyclicBarrier barrier = new CyclicBarrier(4, () -> {
              System.out.println("Program Ended");
      });
      

      这里4 是必须在屏障上等待的线程数,当 4 个不同的线程“到达”屏障时将显示“程序结束”。

      线程经过处理后可能会到达屏障,例如:

      new Thread(() -> {
          while (!done()) {
              ....
          }
          barrier.await();  // replace the flag boolean
      });
      

      请注意,屏障是循环的。这意味着它可以在激活后重复使用。与CountDownLatch相反。

      【讨论】:

        【解决方案3】:

        不保证您的 if 块在所有线程之后运行。您必须通过在每个线程上调用 thread.join() 来显式地让您的主线程等待这些线程:

        thread1.start();
        thread2.start();
        thread3.start();
        thread4.start();
        
        thread1.join();
        thread2.join();
        thread3.join();
        thread4.join();
        
        if (exit && exit2 && exit3 && exit4) {
            System.out.println("Program Ended");
        }
        

        这将确保if 块仅在每个线程死亡后运行。

        【讨论】:

          【解决方案4】:

          在线程较多的情况下,使用ThreadGroup管理多线程可能会更加优雅和方便。

          示例代码:

          ThreadGroup tg = new ThreadGroup("runner");
          
          new Thread(tg, () -> {
              // ...
          }, "t-1").start();
          
          new Thread(tg, () -> {
              // ...
          }, "t-2").start();
          
          // create more  threads,
          
          Thread[] tArr = new Thread[tg.activeCount()];
          cg.enumerate(tArr); // get threads,
          
          // wait all consumers to finish,
          for (Thread t : tArr) {
              t.join();
          }
          

          提示:

          • 创建新线程时,在构造函数中指定线程组。
          • 启动所有子线程后,从线程组中获取线程,并加入每个线程。

          顺便说一句:

          • ThreadGroup.activeCount() 只会返回尚未终止的线程。

          【讨论】:

            猜你喜欢
            • 1970-01-01
            • 2021-10-31
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2011-04-20
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多