尽管被要求通过中断终止,线程仍会徘徊

问题描述 投票:0回答:1

我有一些像这样的Java代码:

IntStream.range(0, N)
        .parallel()
        .forEach(
            i -> {
// do some work
            });    

运行此代码时会看到以下警告:

[WARNING] thread Thread[#73,ForkJoinPool.commonPool-worker-8,5,] was interrupted but is still alive after waiting at least 15000msecs
[WARNING] thread Thread[#73,ForkJoinPool.commonPool-worker-8,5,] will linger despite being asked to die via interruption
[WARNING] thread Thread[#74,ForkJoinPool.commonPool-worker-9,5,] will linger despite being asked to die via interruption
[WARNING] thread Thread[#75,ForkJoinPool.commonPool-worker-10,5,] will linger despite being asked to die via interruption
[WARNING] thread Thread[#76,ForkJoinPool.commonPool-worker-11,5,] will linger despite being asked to die via interruption
[WARNING] thread Thread[#77,ForkJoinPool.commonPool-worker-12,5,] will linger despite being asked to die via interruption
[WARNING] thread Thread[#78,ForkJoinPool.commonPool-worker-13,5,] will linger despite being asked to die via interruption
[WARNING] thread Thread[#79,ForkJoinPool.commonPool-worker-14,5,] will linger despite being asked to die via interruption
[WARNING] NOTE: 7 thread(s) did not finish despite being asked to via interruption. This is not a problem with exec:java, it is a problem with the running code. Although not serious, it should be remedied.

如果不复制粘贴 lambda 中的所有代码,我就无法提供最低限度可重现的示例,这是不可行的,但我已经验证了以下内容:

  • lambda 中没有抛出异常
  • 如果我使用
    mvn spring-boot:run
    运行应用程序,警告就会消失,但如果通过
    mvn exec:java
    执行应用程序,警告就会出现。据我了解,前者会产生一个新的 JVM,而后者则不会。

如果有任何帮助或提示来解决此问题,我将不胜感激。

java multithreading
1个回答
0
投票

据我所知,这是另一个 Maven 问题,因为如果直接通过

java
执行代码,则不会出现错误或警告。

我认为解释是,当使用

mvn exec:java
执行程序时,程序不会在主线程上运行。 Maven 在工作线程上运行程序 [1]:

Thread bootstrapThread = new Thread(
                threadGroup,
                () -> {
                    int sepIndex = mainClass.indexOf('/');

                    final String bootClassName;
...
mainHandle.invoke(arguments); // runs our main class
...
        bootstrapThread.start();
        joinNonDaemonThreads(threadGroup);
...

并且

ForkJoin
公共池中的线程在主线程退出之前不会关闭[2]:

这个池是静态构建的;它的运行状态不受尝试 shutdown() 或 shutdownNow() 的影响。然而,这个池和任何正在进行的处理都会在程序 System.exit(int) 时自动终止。

因此打断它们不会关闭它们[3]。

// executed as a result of call to joinNonDaemonThreads
if (thread.isAlive()) // generally abnormal
        {
            getLog().warn("thread " + thread + " was interrupted but is still alive after waiting at least "
                    + timeoutMsecs + "msecs");
        }

只是我的猜测。

© www.soinside.com 2019 - 2024. All rights reserved.