在完成所有线程之前从java方法返回

时间:2018-10-29 00:08:31

标签: java multithreading thread-safety threadpool

是否有可能在所有线程完成之前从启动线程的java方法返回?

这是我的代码:

import java.util.concurrent.*;

public class ExecutorSample {
    public static void main(String[] args) {
        ExecutorService service = Executors.newCachedThreadPool();
        for (int i = 0; i < 10; i++) {
            service.execute(() -> {
                while (true) {
                }
            });
        }
        return;
    }
}

由于某种我不了解的原因而无法返回。为什么主线程的返回会受到工作线程卡住的影响?

1 个答案:

答案 0 :(得分:5)

您的main方法正在返回,但是问题在于您的JVM没有退出。您可以通过将main方法重命名为doMain()之类的其他方法,然后将main编写为:

public static void main(String[] args) {
    doMain();
    System.out.printf("here");
}

您会看到确实得到了输出,但是程序没有结束。

正在发生的事情是Executors.newCachedThreadPool使用default thread factory,它创建了非守护线程。当您的main方法返回时,JVM将等待所有非守护程序线程完成(这是它们与守护程序线程的区别-JVM不等待那些线程)。由于您所有的Runnable都将永远运行,因此非守护进程线程将永远不会完成,并且JVM将永远不会退出。

你能做什么?一些选项:

  • 使用重载newCachedThreadPool(ThreadFactory),提供一个创建守护程序线程的ThreadFactory
  • 在您的ExecutorService上使用shutdownNow()。这将在每个正在运行的线程上发送一个中断。您仍然必须在每个线程上进行检查,方法是调用引发InterruptedException的方法或显式调用Thread.currentThread().isInterrupted()

对于shutdownNow方法,请注意,仅中断线程本身不足以停止该线程-在该线程上运行的代码必须通过检查其中断状态来配合(使用这两种方法之一)并适当退出。例如,您可以将while(true)替换为while (!Thread.currentThread().isInterrupted())