Java 为什么可以';线程停止工作后,我是否运行main()中的语句?

Java 为什么可以';线程停止工作后,我是否运行main()中的语句?,java,multithreading,parallel-processing,Java,Multithreading,Parallel Processing,所以我有一个有4个线程的程序,所有线程都在运行。 其中3个线程始终在运行,即使程序完成其工作时也是如此。 所以我创建了一些变量,让它们停止 我将while(true)更改为while(exit),程序运行正常 在线程之后,我想运行一些其他语句,但前提是线程已经停止 我尝试使用4个变量,exit、exit1、exit2、exit3,并将它们设置为false。线程将完成并使这些变量为真 大体上,在Thread.start()之后,如果我想打印一些东西,它不会打印 Thread1.start(); T

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

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

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

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

大体上,在
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 
}

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

Thread类有一个方法可以执行该操作,因为您将一直阻止,直到线程完成执行。教程如何使用
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块不能保证在所有线程之后运行。您必须通过对每个线程调用
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");
}

<>这将确保<代码>如果块只在每个线程都已死亡之后运行。

< P>作为替代,您应该考虑<代码> CyclicBarrier < /C> >或<代码> CurtDutLaCH < /C>。 与自定义终止线程标志相比,这些标志不太容易出错,通常不太详细,效率也相当高

它们有各自的特点,但非常接近。
CountDownLatch
将“倒计时”操作的计数器关联到reach以继续,而
CyclicBarrier
将调用
wait()
以应用特定处理的不同线程的计数器关联到reach

使用
CyclicBarrier
它可能看起来像:

CyclicBarrier barrier = new CyclicBarrier(4, () -> {
        System.out.println("Program Ended");
});
此处
4
是必须在屏障上等待的线程数,当4个不同的线程“到达”屏障时,将显示“程序结束”

螺纹在加工后可到达屏障,例如:

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

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

相反,当有很多线程时,使用
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()
    将只返回尚未终止的线程