当前位置: 首页 > 知识库问答 >
问题:

为什么以下应用程序在使用ForkJoinPool时立即终止,而在我使用ThreadPoolExecator时却没有?

赵钊
2023-03-14

我试图理解ForkJoinPool和ThreadPoolExector之间的一些区别,下面引起了我的注意。

使用ThreadPoolExecator

public static void main(String[] args) {
    ExecutorService es = Executors.newCachedThreadPool();
    es.execute(() -> System.out.println("Hello."));
    es.shutdown();
}

该程序将始终打印“你好”对着屏幕。

带ForkJoinPool

public static void main(String[] args) {
    ForkJoinPool es = new ForkJoinPool(1);
    es.execute(() -> System.out.println("Hello."));
    es.shutdown();
}

这个程序有时会打印出“你好”到屏幕上。

这到底是怎么回事?

注意,如果调用gracefully shutdown,第一个程序永远不会终止,但在其他方面,两个程序的行为相同。

我理解,可以通过注意到JVM根本不等待执行的线程终止来解释分叉/连接行为,有时线程幸运地在主线程完成之前运行。为什么第一个解决方案没有表现出相同的行为?

我不认为答案是两者的行为实际上是相同的,当我运行第一个解决方案时,我只是运气好。事实上,当我运行第一个解决方案100次时,我得到了“Hello”。所有100次,但当我运行第二个100次时,我得到了“Hello”。大约10次。即使“始终”这个词并不完全正确,但这两个词的工作方式似乎存在关键差异,导致了明显不同的行为。

共有1个答案

伏子辰
2023-03-14

ForkJoinPool是用守护进程线程定义的。也就是说,FJP创建的每个线程都是setDaemon(true)。一旦只有守护进程线程运行,JVM将立即终止。

您可能应该关闭,然后等待终止。

 类似资料:
  • 问题内容: 我正在尝试使用编写一个简单的代码,但是只是不愿等待它假定的时间而代码立即执行。我究竟做错了什么? 问题答案: 您正在立即调用该函数并计划其返回值。 使用: 注意:没有原谅。

  • 试图在docker中运行的简单Spring Boot应用程序,但在docker运行后,会立即退出。这是我的文件 Docker运行命令 在容器日志中,唯一的输出是Spring横幅,然后容器终止。 我错过了什么吗?

  • 我使用的是IntelliJIDEA CE edition(11.0.4)的最新版本。有一件事我在任何地方都找不到,它阻碍了我对Java/Spring的进一步改进。 控制器: 类:导入com.example.demo.interfaces.ISave; 类接口: 没什么特别的,只是为了掌握Spring和Java。 在我的控制器里,当我试图使用 我收到一个阻止应用启动的错误。以下是错误: 任务应用程序

  • 问题内容: 为什么以及何时应该在php中使用该函数?使用后是否应该始终使用它?我读到我必须使用它来防止会话固定,这是唯一原因吗? 问题答案: 什么啊 就像函数名称所说的那样,它是一个函数,它将用新的ID替换当前的会话ID,并保留当前的会话信息。 它有什么作用? 它主要有助于防止会话固定攻击。会话固定攻击是恶意用户试图利用系统中的漏洞固定(设置)另一个用户的会话ID(SID)的地方。这样,他们将拥有

  • 我们知道,JVM同时使用解释器和JIT编译器。JIT编译器将重复的字节码转换为机器码并存储在内存中。现在,当解释器逐行翻译字节码并运行它时,它将跳过已转换并存储在内存中的重复代码的翻译部分,但将直接运行它。从而减少了并发冗余翻译。 那么为什么Java在JVM中使用解释器呢?像JIT这样的编译器可以一次性完成将字节码转换为机器码的整个任务吗?

  • 当我阅读Java中的System.nanoTime()API时。我发现了这句台词: 一个应该使用t1-t0<0,而不是t1 Java整数compareTo()-为什么使用比较与减法? 这两件事产生矛盾。