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

Jes*_*ica 4 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;
    }
}
Run Code Online (Sandbox Code Playgroud)

由于我不理解的某些原因,这不会返回.为什么主线程的返回受到工作线程卡住的影响?

ysh*_*vit 5

您的main方法正在返回,但问题是您的JVM没有退出.您可以通过将main方法重命名为其他方式来测试,例如doMain(),然后写main为:

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

你会看到你确实得到了输出,但程序并没有结束.

发生的事情是Executors.newCachedThreadPool使用默认的线程工厂,它创建非守护程序线程.当您的main方法返回时,JVM将等待所有非守护程序线程完成(这就是它们与守护程序线程的区别--JVM不会等待它们).由于所有Runnable都会永远运行,因此非守护程序线程永远不会完成,JVM永远不会退出.

你能做什么?一些选择:

  • 使用重载newCachedThreadPool(ThreadFactory),提供一个创建守护程序线程的ThreadFactory
  • shutdownNow()在ExecutorService上使用.这将在每个正在运行的线程上发送一个中断.您仍然需要通过调用抛出的方法InterruptedException或显式调用来检查每个线程上的内容Thread.currentThread().isInterrupted().

对于shutdownNow方法,注意自身中断线程是足够阻止它-代码运行在该线程已经通过(使用这两种方法之一),其中断状态检查和适当地退出合作.例如,您可以替换while(true)while (!Thread.currentThread().isInterrupted()).