线程停止工作后,为什么不能在main()中运行语句?

时间:2019-01-05 15:54:11

标签: java multithreading parallel-processing

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

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

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

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

主要,在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 
}

是否有办法确保仅在线程停止后才运行某些语句?

4 个答案:

答案 0 :(得分: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");
}

答案 1 :(得分:0)

您的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块仅在每个线程死亡后才运行。

答案 2 :(得分:0)

作为替代方案,您应考虑使用CyclicBarrierCountDownLatch
与自定义终止线程标志相比,它们不易出错,通常较不冗长且相当有效。

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

使用CyclicBarrier时,它看起来像:

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

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

线程在处理之后可能会达到障碍,例如:

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

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

答案 3 :(得分:0)

在线程很多的情况下,使用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()将仅返回尚未终止的线程。