我需要清理 Java 中的 Thread 对象吗?

Do I need to clean up Thread objects in Java?

在我的 Java 应用程序中,我有一个 Runnable,例如:

this.runner = new Runnable({
    @Override
    public void run() {
        // do something that takes roughly 5 seconds.
    }
});

我需要在单独的线程中大约每 30 秒(尽管这可能会有所不同)运行。代码的性质是这样的,我可以 运行 它而忘记它(无论它成功还是失败)。我在我的应用程序中按如下方式执行此操作作为一行代码:

(new Thread(this.runner)).start()

现在,这工作正常。但是,我想知道在每个线程实例完成 运行ning 之后,我是否应该对它们进行任何类型的清理?我正在 VisualVM 中对此应用程序进行 CPU 分析,我可以看到,在 1 小时 运行 的过程中,正在创建大量线程。这种担忧是否有效或一切正常?

N.B。我开始 new Thread 而不是简单地将 this.runner 定义为 Thread 的原因是我有时需要同时 运行 this.runner 两次(在第一个 运行 调用已完成),如果我将 this.runner 定义为 Thread,我将无法执行此操作,因为单个 Thread 对象只能再次 运行 一次初始执​​行已完成。

我建议您查看并发性 API。有许多预定义的通用方法。通过使用 ExecutorService 可以在向执行器提交任务后调用 shutdown 方法,执行器停止接受新任务,等待之前提交的任务执行完毕,然后终止执行器。 简短介绍: https://www.baeldung.com/java-executor-service-tutorial

Java对象需要"cleaned up"或"closed"使用后按惯例实现AutoCloseable interface. This makes it easy to do the clean up using try-with-resources. The Threadclass不实现AutoCloseable,并且没有 "close" 或 "dispose" 方法。因此,您不需要进行任何显式清理。

但是

(new Thread(this.runner)).start()

不保证立即开始 Runnable 的计算。您可能不关心它是成功还是失败,但我猜您 确实 关心它是否 运行。您可能希望同时限制这些任务的数量 运行ning。例如,您可能一次只想要一个到 运行。所以你可能想要 join() the thread (or, perhaps, join with a timeout)。加入线程将确保线程将完成其计算。使用超时加入线程会增加线程开始其计算的机会(因为当前线程将被挂起,释放 CPU 可能 运行 另一个线程)。

但是,不建议创建多个线程来执行常规或频繁的任务。你应该改为 submit tasks to a thread pool. That will enable you to control the maximum amount of concurrency, and can provide you with other benefits (such as prioritising different tasks), and amortises the expense of creating threads.

您可以将线程池​​配置为使用固定长度(有界)的任务队列,并导致提交线程到 execute submitted tasks itself themselves when the queue is full. By doing that you can guarantee that tasks submitted to the thread pool are (eventually) executed. The documentation of ThreadPool.execute(Runnable) 表示

Executes the given task sometime in the future

这表明实施保证它最终将 运行 所有提交的任务 即使 您不执行那些特定任务以确保执行提交的任务。