java - ScheduledExecutorService 生命周期?

标签 java multithreading daemon executor

我有一个对象需要在对象本身存在时定期做一些工作,所以我设计了如下内容。基本上是一个 Main 类,其中包含对 ScheduledExecutorService 实例的引用。在这个例子中,所有的周期性工作就是打印一个字符串到std。

我希望代码的行为如下所示:

  1. test2 被调用,它创建一个 Main 对象 o1(其中有一个 ScheduledExecutorService)。
  2. test2 注册为每秒在 o1 上打印一行。
  3. test2 返回,o1 变成垃圾。
  4. 系统 gc 启动到 gc o1,它有一个 finalize 方法来关闭它的本地调度程序。

但是,如果我运行这个程序,它会一直运行下去。基本上 gc 从不调用 o1 的终结器,因此,调度程序永远不会关闭,因此,即使主线程结束,程序仍然不会退出。

现在,如果我在 test2() 中注释掉 o1.register,程序就会正常运行,例如gc 调用等。同样在调试器中,似乎只有在调用 ScheduledExecutorService.schedule 之后才会创建实际线程。

任何解释发生了什么?

public class Main {

public static void main(String[] args) throws Exception {
    test2();

    System.gc();
    System.out.println("Waiting for finalize to be called..");
    Thread.sleep(5000);
}

private static void test2() throws Exception {
    Main o1 = new Main();
    o1.register();
    Thread.sleep(5000);     
}

private final ScheduledExecutorService _scheduler = Executors.newSingleThreadScheduledExecutor();   

private void register() {
    _scheduler.scheduleWithFixedDelay(new Runnable() { 
        @Override public void run() { 
            System.out.println("!doing stuff...");
            }
        }, 1, 1, TimeUnit.SECONDS);
}

@Override
protected void finalize() throws Throwable  {
    try {
        System.out.print("bye");
        _scheduler.shutdown();          
    } finally {
        super.finalize();
    }       
}

最佳答案

两个问题:

  1. 默认线程工厂创建非守护进程 线程。主线程可以结束,但只要有 Activity 的非守护线程,JVM 就不会终止。我相信您将需要编写一个自定义线程工厂来创建守护线程。
  2. 不要依赖于终结器的调用——无法保证终结器会在任何特定时间或永远被调用。此外,System.gc() 调用被定义为对 JVM 的建议,而不是命令。 API文档中的措辞是

Calling the gc method suggests that the Java Virtual Machine expend effort toward recycling unused objects ...

关于java - ScheduledExecutorService 生命周期?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/3384375/

相关文章:

c++ - 多源BFS多线程

php - 如何制作用于RabbitMQ PHP任务消费的Docker容器

java - JUnit 测试杀死守护进程

java - Jenkins Jelly 更新文本框

c# - .NET Async 中的可伸缩性与响应能力

c - 为什么当线程 A 关闭套接字对的末端时,windows select() 并不总是通知线程 B 的 select()?

python - 如何在 Python 中生成一个新的独立进程

java - 确定两个对象之间的差异

java - 如何使用CloudFileClient从azure文件存储获取文件内容(字节数组)?

java - 在后台接收 GPS 位置更新